From f1b99e6658dc6899ec502cc66fcc83e5b1aca7cd Mon Sep 17 00:00:00 2001 From: Anastasia Nogovitcina Date: Mon, 23 Mar 2026 08:40:34 +0100 Subject: [PATCH 1/3] part_1 --- .gitignore | 32 ++++++++ conftest.py | 9 +++ helpers.py | 20 +++++ locators/__init__.py | 0 locators/locators.py | 81 +++++++++++++++++++ praktikum/__init__.py | 0 praktikum/bun.py | 10 +++ praktikum/burger.py | 34 ++++++++ praktikum/database.py | 27 +++++++ praktikum/ingredient.py | 14 ++++ praktikum/ingredient_types.py | 2 + pytest.ini | 2 + requirements.txt | 2 + tests/__init__.py | 0 tests/test_bun.py | 23 ++++++ tests/test_burger.py | 142 +++++++++++++++++++++++++++++++++ tests/test_constructor.py | 17 ++++ tests/test_database.py | 32 ++++++++ tests/test_ingredient.py | 32 ++++++++ tests/test_login.py | 93 +++++++++++++++++++++ tests/test_personal_account.py | 87 ++++++++++++++++++++ tests/test_registration.py | 40 ++++++++++ 22 files changed, 699 insertions(+) create mode 100644 .gitignore create mode 100644 conftest.py create mode 100644 helpers.py create mode 100644 locators/__init__.py create mode 100644 locators/locators.py create mode 100644 praktikum/__init__.py create mode 100644 praktikum/bun.py create mode 100644 praktikum/burger.py create mode 100644 praktikum/database.py create mode 100644 praktikum/ingredient.py create mode 100644 praktikum/ingredient_types.py create mode 100644 pytest.ini create mode 100644 requirements.txt create mode 100644 tests/__init__.py create mode 100644 tests/test_bun.py create mode 100644 tests/test_burger.py create mode 100644 tests/test_constructor.py create mode 100644 tests/test_database.py create mode 100644 tests/test_ingredient.py create mode 100644 tests/test_login.py create mode 100644 tests/test_personal_account.py create mode 100644 tests/test_registration.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..0d7af75bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,32 @@ +# Python +__pycache__/ +*.py[cod] +*.pyo +.pytest_cache/ +*.egg-info/ +dist/ +build/ +.eggs/ + +# Virtual environment +venv/ +.venv/ +env/ + +# IDE +.idea/ +.vscode/ +*.iml + +# OS +.DS_Store +Thumbs.db + +# Logs and reports +*.log +reports/ +allure-results/ + +# Selenium / browser +chromedriver +geckodriver diff --git a/conftest.py b/conftest.py new file mode 100644 index 000000000..85f8d355d --- /dev/null +++ b/conftest.py @@ -0,0 +1,9 @@ +import pytest +from selenium import webdriver + + +@pytest.fixture +def driver(): + driver = webdriver.Chrome() + yield driver + driver.quit() \ No newline at end of file diff --git a/helpers.py b/helpers.py new file mode 100644 index 000000000..a9a87f0e3 --- /dev/null +++ b/helpers.py @@ -0,0 +1,20 @@ +import random +import string + +BASE_URL = "https://stellarburgers.education-services.ru" +LOGIN_URL = f"{BASE_URL}/login" +REGISTER_URL = f"{BASE_URL}/register" +FORGOT_PASSWORD_URL = f"{BASE_URL}/forgot-password" +PROFILE_URL = f"{BASE_URL}/account/profile" + + +def generate_email(): + """Генерирует уникальный email в формате имя_фамилия_когорта_XXX@домен.""" + digits = "".join(random.choices(string.digits, k=6)) + return f"test_testov_999_{digits}@yandex.ru" + + +def generate_password(length=8): + """Генерирует случайный пароль заданной длины (минимум 6 символов).""" + chars = string.ascii_letters + string.digits + return "".join(random.choices(chars, k=length)) diff --git a/locators/__init__.py b/locators/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/locators/locators.py b/locators/locators.py new file mode 100644 index 000000000..fb1333969 --- /dev/null +++ b/locators/locators.py @@ -0,0 +1,81 @@ +from selenium.webdriver.common.by import By + + +class MainPageLocators: + # Кнопка «Войти в аккаунт» в конструкторе (видна только неавторизованным) + LOGIN_BUTTON = (By.XPATH, "//button[text()='Войти в аккаунт']") + + # Ссылка «Личный Кабинет» в шапке (тег ) + PERSONAL_ACCOUNT_LINK = (By.XPATH, "//a[@href='/account']") + + # Ссылка «Конструктор» в шапке (тег ) + CONSTRUCTOR_LINK = (By.XPATH, "//a[@href='/'][.//p[contains(@class,'AppHeader_header__linkText')]]") + + # Логотип Stellar Burgers в шапке (div-обёртка с классом header__logo) + LOGO = (By.XPATH, "//div[contains(@class,'AppHeader_header__logo')]") + + # Вкладка «Булки» в конструкторе (кликабельный div с текстом внутри span) + BUNS_TAB = (By.XPATH, "//div[contains(@class,'tab_tab')]//span[text()='Булки']") + + # Вкладка «Соусы» в конструкторе + SAUCES_TAB = (By.XPATH, "//div[contains(@class,'tab_tab')]//span[text()='Соусы']") + + # Вкладка «Начинки» в конструкторе + FILLINGS_TAB = (By.XPATH, "//div[contains(@class,'tab_tab')]//span[text()='Начинки']") + + # Заголовок раздела «Булки» в списке ингредиентов (h2) + BUNS_HEADING = (By.XPATH, "//h2[text()='Булки']") + + # Заголовок раздела «Соусы» в списке ингредиентов (h2) + SAUCES_HEADING = (By.XPATH, "//h2[text()='Соусы']") + + # Заголовок раздела «Начинки» в списке ингредиентов (h2) + FILLINGS_HEADING = (By.XPATH, "//h2[text()='Начинки']") + + +class LoginPageLocators: + # Поле ввода email на странице входа (первый fieldset, оба поля имеют name="name") + EMAIL_INPUT = (By.XPATH, "//fieldset[1]//input") + + # Поле ввода пароля на странице входа (второй fieldset, name="Пароль") + PASSWORD_INPUT = (By.XPATH, "//input[@name='Пароль']") + + # Кнопка «Войти» на странице входа + LOGIN_BUTTON = (By.XPATH, "//button[text()='Войти']") + + # Ссылка «Зарегистрироваться» на странице входа (класс Auth_link) + REGISTER_LINK = (By.XPATH, "//a[@href='/register']") + + # Ссылка «Восстановить пароль» на странице входа + FORGOT_PASSWORD_LINK = (By.XPATH, "//a[@href='/forgot-password']") + + +class RegisterPageLocators: + # Поле «Имя» на странице регистрации (первый fieldset) + NAME_INPUT = (By.XPATH, "//fieldset[1]//input") + + # Поле «Email» на странице регистрации (второй fieldset) + EMAIL_INPUT = (By.XPATH, "//fieldset[2]//input") + + # Поле «Пароль» на странице регистрации (третий fieldset) + PASSWORD_INPUT = (By.XPATH, "//fieldset[3]//input") + + # Кнопка «Зарегистрироваться» + REGISTER_BUTTON = (By.XPATH, "//button[text()='Зарегистрироваться']") + + # Ссылка «Войти» на странице регистрации (ведёт на /login) + LOGIN_LINK = (By.XPATH, "//a[@href='/login']") + + # Сообщение об ошибке при некорректном пароле + PASSWORD_ERROR = (By.XPATH, "//p[text()='Некорректный пароль']") + + +class ForgotPasswordPageLocators: + # Ссылка «Войти» на странице восстановления пароля (ведёт на /login) + LOGIN_LINK = (By.XPATH, "//a[@href='/login']") + + +class ProfilePageLocators: + # Кнопка «Выйти» в боковом меню личного кабинета + LOGOUT_BUTTON = (By.XPATH, "//button[text()='Выход']") + diff --git a/praktikum/__init__.py b/praktikum/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/praktikum/bun.py b/praktikum/bun.py new file mode 100644 index 000000000..d0a826c2d --- /dev/null +++ b/praktikum/bun.py @@ -0,0 +1,10 @@ +class Bun: + def __init__(self, name: str, price: float): + self.name = name + self.price = price + + def get_name(self) -> str: + return self.name + + def get_price(self) -> float: + return self.price diff --git a/praktikum/burger.py b/praktikum/burger.py new file mode 100644 index 000000000..4e28963fc --- /dev/null +++ b/praktikum/burger.py @@ -0,0 +1,34 @@ +from typing import List +from praktikum.bun import Bun +from praktikum.ingredient import Ingredient + +class Burger: + def __init__(self): + self.bun = None + self.ingredients: List[Ingredient] = [] + + def set_buns(self, bun: Bun): + self.bun = bun + + def add_ingredient(self, ingredient: Ingredient): + self.ingredients.append(ingredient) + + def remove_ingredient(self, index: int): + del self.ingredients[index] + + def move_ingredient(self, index: int, new_index: int): + self.ingredients.insert(new_index, self.ingredients.pop(index)) + + def get_price(self) -> float: + price = self.bun.get_price() * 2 + for ingredient in self.ingredients: + price += ingredient.get_price() + return price + + def get_receipt(self) -> str: + receipt: List[str] = [f'(==== {self.bun.get_name()} ====)'] + for ingredient in self.ingredients: + receipt.append(f'= {str(ingredient.get_type()).lower()} {ingredient.get_name()} =') + receipt.append(f'(==== {self.bun.get_name()} ====)\n') + receipt.append(f'Price: {self.get_price()}') + return '\n'.join(receipt) diff --git a/praktikum/database.py b/praktikum/database.py new file mode 100644 index 000000000..17a244243 --- /dev/null +++ b/praktikum/database.py @@ -0,0 +1,27 @@ +from typing import List +from praktikum.bun import Bun +from praktikum.ingredient import Ingredient +from praktikum.ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING + +class Database: + def __init__(self): + self.buns: List[Bun] = [] + self.ingredients: List[Ingredient] = [] + + self.buns.append(Bun("black bun", 100)) + self.buns.append(Bun("white bun", 200)) + self.buns.append(Bun("red bun", 300)) + + self.ingredients.append(Ingredient(INGREDIENT_TYPE_SAUCE, "hot sauce", 100)) + self.ingredients.append(Ingredient(INGREDIENT_TYPE_SAUCE, "sour cream", 200)) + self.ingredients.append(Ingredient(INGREDIENT_TYPE_SAUCE, "chili sauce", 300)) + + self.ingredients.append(Ingredient(INGREDIENT_TYPE_FILLING, "cutlet", 100)) + self.ingredients.append(Ingredient(INGREDIENT_TYPE_FILLING, "dinosaur", 200)) + self.ingredients.append(Ingredient(INGREDIENT_TYPE_FILLING, "sausage", 300)) + + def available_buns(self) -> List[Bun]: + return self.buns + + def available_ingredients(self) -> List[Ingredient]: + return self.ingredients diff --git a/praktikum/ingredient.py b/praktikum/ingredient.py new file mode 100644 index 000000000..0a8350eae --- /dev/null +++ b/praktikum/ingredient.py @@ -0,0 +1,14 @@ +class Ingredient: + def __init__(self, ingredient_type: str, name: str, price: float): + self.type = ingredient_type + self.name = name + self.price = price + + def get_price(self) -> float: + return self.price + + def get_name(self) -> str: + return self.name + + def get_type(self) -> str: + return self.type diff --git a/praktikum/ingredient_types.py b/praktikum/ingredient_types.py new file mode 100644 index 000000000..84e983fff --- /dev/null +++ b/praktikum/ingredient_types.py @@ -0,0 +1,2 @@ +INGREDIENT_TYPE_SAUCE = 'SAUCE' +INGREDIENT_TYPE_FILLING = 'FILLING' diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 000000000..a635c5c03 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +pythonpath = . diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..78b9d1e15 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +pytest==8.2.0 +pytest-cov==5.0.0 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test_bun.py b/tests/test_bun.py new file mode 100644 index 000000000..db4372a31 --- /dev/null +++ b/tests/test_bun.py @@ -0,0 +1,23 @@ +import pytest +from praktikum.bun import Bun + + +class TestBun: + + @pytest.mark.parametrize('name, price', [ + ('black bun', 100), + ('white bun', 200.5), + ('red bun', 0), + ]) + def test_get_name(self, name, price): + bun = Bun(name, price) + assert bun.get_name() == name + + @pytest.mark.parametrize('name, price', [ + ('black bun', 100), + ('white bun', 200.5), + ('red bun', 0), + ]) + def test_get_price(self, name, price): + bun = Bun(name, price) + assert bun.get_price() == price diff --git a/tests/test_burger.py b/tests/test_burger.py new file mode 100644 index 000000000..c1bf2afd9 --- /dev/null +++ b/tests/test_burger.py @@ -0,0 +1,142 @@ +import pytest +from unittest.mock import MagicMock +from praktikum.burger import Burger +from praktikum.bun import Bun +from praktikum.ingredient import Ingredient +from praktikum.ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING + + +@pytest.fixture +def mock_bun(): + bun = MagicMock(spec=Bun) + bun.get_name.return_value = 'black bun' + bun.get_price.return_value = 100 + return bun + + +@pytest.fixture +def mock_sauce(): + ingredient = MagicMock(spec=Ingredient) + ingredient.get_name.return_value = 'hot sauce' + ingredient.get_price.return_value = 50 + ingredient.get_type.return_value = INGREDIENT_TYPE_SAUCE + return ingredient + + +@pytest.fixture +def mock_filling(): + ingredient = MagicMock(spec=Ingredient) + ingredient.get_name.return_value = 'cutlet' + ingredient.get_price.return_value = 100 + ingredient.get_type.return_value = INGREDIENT_TYPE_FILLING + return ingredient + + +@pytest.fixture +def burger_with_bun(mock_bun): + burger = Burger() + burger.set_buns(mock_bun) + return burger + + +class TestBurgerSetBuns: + + def test_set_buns(self, mock_bun): + burger = Burger() + burger.set_buns(mock_bun) + assert burger.bun == mock_bun + + +class TestBurgerAddIngredient: + + def test_add_ingredient(self, burger_with_bun, mock_sauce): + burger_with_bun.add_ingredient(mock_sauce) + assert mock_sauce in burger_with_bun.ingredients + + def test_add_multiple_ingredients(self, burger_with_bun, mock_sauce, mock_filling): + burger_with_bun.add_ingredient(mock_sauce) + burger_with_bun.add_ingredient(mock_filling) + assert len(burger_with_bun.ingredients) == 2 + + +class TestBurgerRemoveIngredient: + + def test_remove_ingredient(self, burger_with_bun, mock_sauce, mock_filling): + burger_with_bun.add_ingredient(mock_sauce) + burger_with_bun.add_ingredient(mock_filling) + burger_with_bun.remove_ingredient(0) + assert mock_sauce not in burger_with_bun.ingredients + + def test_remove_ingredient_reduces_count(self, burger_with_bun, mock_sauce): + burger_with_bun.add_ingredient(mock_sauce) + burger_with_bun.remove_ingredient(0) + assert len(burger_with_bun.ingredients) == 0 + + +class TestBurgerMoveIngredient: + + def test_move_ingredient(self, burger_with_bun, mock_sauce, mock_filling): + burger_with_bun.add_ingredient(mock_sauce) + burger_with_bun.add_ingredient(mock_filling) + burger_with_bun.move_ingredient(1, 0) + assert burger_with_bun.ingredients[0] == mock_filling + assert burger_with_bun.ingredients[1] == mock_sauce + + +class TestBurgerGetPrice: + + def test_get_price_bun_only(self, burger_with_bun): + assert burger_with_bun.get_price() == 200 + + def test_get_price_with_ingredients(self, burger_with_bun, mock_sauce, mock_filling): + burger_with_bun.add_ingredient(mock_sauce) + burger_with_bun.add_ingredient(mock_filling) + assert burger_with_bun.get_price() == 350 + + @pytest.mark.parametrize('bun_price, ingredient_prices, expected', [ + (100, [], 200), + (100, [50], 250), + (200, [100, 150], 650), + ]) + def test_get_price_parametrized(self, bun_price, ingredient_prices, expected): + bun = MagicMock(spec=Bun) + bun.get_price.return_value = bun_price + bun.get_name.return_value = 'bun' + + burger = Burger() + burger.set_buns(bun) + + for price in ingredient_prices: + ingredient = MagicMock(spec=Ingredient) + ingredient.get_price.return_value = price + ingredient.get_name.return_value = 'ing' + ingredient.get_type.return_value = INGREDIENT_TYPE_SAUCE + burger.add_ingredient(ingredient) + + assert burger.get_price() == expected + + +class TestBurgerGetReceipt: + + def test_get_receipt_contains_bun_name(self, burger_with_bun): + assert 'black bun' in burger_with_bun.get_receipt() + + def test_get_receipt_contains_price(self, burger_with_bun): + assert 'Price: 200' in burger_with_bun.get_receipt() + + def test_get_receipt_contains_ingredient_name(self, burger_with_bun, mock_sauce): + burger_with_bun.add_ingredient(mock_sauce) + assert 'hot sauce' in burger_with_bun.get_receipt() + + def test_get_receipt_contains_ingredient_type(self, burger_with_bun, mock_sauce): + burger_with_bun.add_ingredient(mock_sauce) + assert 'sauce' in burger_with_bun.get_receipt() + + def test_get_receipt_format(self, burger_with_bun, mock_sauce): + burger_with_bun.add_ingredient(mock_sauce) + receipt = burger_with_bun.get_receipt() + + lines = receipt.split('\n') + + assert lines[0] == '(==== black bun ====)' + assert '(==== black bun ====)' in lines diff --git a/tests/test_constructor.py b/tests/test_constructor.py new file mode 100644 index 000000000..6a8648735 --- /dev/null +++ b/tests/test_constructor.py @@ -0,0 +1,17 @@ +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC + +from helpers import BASE_URL +from locators.locators import MainPageLocators + + +def test_navigate_to_buns(driver): + wait = WebDriverWait(driver, 5) + + driver.get(BASE_URL) + + heading = wait.until( + EC.visibility_of_element_located(MainPageLocators.BUNS_HEADING) + ) + + assert heading.is_displayed() \ No newline at end of file diff --git a/tests/test_database.py b/tests/test_database.py new file mode 100644 index 000000000..8c52e4565 --- /dev/null +++ b/tests/test_database.py @@ -0,0 +1,32 @@ +from praktikum.database import Database +from praktikum.bun import Bun +from praktikum.ingredient import Ingredient + + +class TestDatabase: + + def test_available_buns_returns_list(self): + db = Database() + assert isinstance(db.available_buns(), list) + + def test_available_buns_not_empty(self): + db = Database() + assert len(db.available_buns()) > 0 + + def test_available_buns_contains_bun_instances(self): + db = Database() + for bun in db.available_buns(): + assert isinstance(bun, Bun) + + def test_available_ingredients_returns_list(self): + db = Database() + assert isinstance(db.available_ingredients(), list) + + def test_available_ingredients_not_empty(self): + db = Database() + assert len(db.available_ingredients()) > 0 + + def test_available_ingredients_contains_ingredient_instances(self): + db = Database() + for ingredient in db.available_ingredients(): + assert isinstance(ingredient, Ingredient) diff --git a/tests/test_ingredient.py b/tests/test_ingredient.py new file mode 100644 index 000000000..cb8ebc9c5 --- /dev/null +++ b/tests/test_ingredient.py @@ -0,0 +1,32 @@ +import pytest +from praktikum.ingredient import Ingredient +from praktikum.ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING + + +class TestIngredient: + + @pytest.mark.parametrize('ingredient_type, name, price', [ + (INGREDIENT_TYPE_SAUCE, 'hot sauce', 100), + (INGREDIENT_TYPE_FILLING, 'cutlet', 200), + (INGREDIENT_TYPE_SAUCE, 'sour cream', 50.5), + ]) + def test_get_name(self, ingredient_type, name, price): + ingredient = Ingredient(ingredient_type, name, price) + assert ingredient.get_name() == name + + @pytest.mark.parametrize('ingredient_type, name, price', [ + (INGREDIENT_TYPE_SAUCE, 'hot sauce', 100), + (INGREDIENT_TYPE_FILLING, 'cutlet', 200), + (INGREDIENT_TYPE_SAUCE, 'sour cream', 50.5), + ]) + def test_get_price(self, ingredient_type, name, price): + ingredient = Ingredient(ingredient_type, name, price) + assert ingredient.get_price() == price + + @pytest.mark.parametrize('ingredient_type, name, price', [ + (INGREDIENT_TYPE_SAUCE, 'hot sauce', 100), + (INGREDIENT_TYPE_FILLING, 'cutlet', 200), + ]) + def test_get_type(self, ingredient_type, name, price): + ingredient = Ingredient(ingredient_type, name, price) + assert ingredient.get_type() == ingredient_type diff --git a/tests/test_login.py b/tests/test_login.py new file mode 100644 index 000000000..1ae2c919a --- /dev/null +++ b/tests/test_login.py @@ -0,0 +1,93 @@ +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC + +from helpers import BASE_URL, LOGIN_URL, REGISTER_URL, FORGOT_PASSWORD_URL, generate_email, generate_password +from locators.locators import MainPageLocators, LoginPageLocators, RegisterPageLocators, ForgotPasswordPageLocators + + +def register_and_get_credentials(driver): + wait = WebDriverWait(driver, 5) + + driver.get(REGISTER_URL) + + email = generate_email() + password = generate_password() + + wait.until(EC.element_to_be_clickable(RegisterPageLocators.NAME_INPUT)).send_keys("Test User") + driver.find_element(*RegisterPageLocators.EMAIL_INPUT).send_keys(email) + driver.find_element(*RegisterPageLocators.PASSWORD_INPUT).send_keys(password) + driver.find_element(*RegisterPageLocators.REGISTER_BUTTON).click() + + wait.until(EC.url_to_be(LOGIN_URL)) + + return email, password + + +class TestLogin: + + def test_login_via_main_button(self, driver): + wait = WebDriverWait(driver, 5) + + email, password = register_and_get_credentials(driver) + + driver.get(BASE_URL) + + wait.until(EC.element_to_be_clickable(MainPageLocators.LOGIN_BUTTON)).click() + + wait.until(EC.visibility_of_element_located(LoginPageLocators.EMAIL_INPUT)).send_keys(email) + driver.find_element(*LoginPageLocators.PASSWORD_INPUT).send_keys(password) + driver.find_element(*LoginPageLocators.LOGIN_BUTTON).click() + + wait.until(EC.url_to_be(BASE_URL + "/")) + assert driver.current_url == BASE_URL + "/" + + def test_login_via_personal_account_link(self, driver): + wait = WebDriverWait(driver, 5) + + email, password = register_and_get_credentials(driver) + + driver.get(BASE_URL) + + wait.until(EC.element_to_be_clickable(MainPageLocators.PERSONAL_ACCOUNT_LINK)).click() + wait.until(EC.url_to_be(LOGIN_URL)) + + wait.until(EC.visibility_of_element_located(LoginPageLocators.EMAIL_INPUT)).send_keys(email) + driver.find_element(*LoginPageLocators.PASSWORD_INPUT).send_keys(password) + driver.find_element(*LoginPageLocators.LOGIN_BUTTON).click() + + wait.until(EC.url_to_be(BASE_URL + "/")) + assert driver.current_url == BASE_URL + "/" + + def test_login_via_register_page_link(self, driver): + wait = WebDriverWait(driver, 5) + + email, password = register_and_get_credentials(driver) + + driver.get(REGISTER_URL) + + wait.until(EC.element_to_be_clickable(RegisterPageLocators.LOGIN_LINK)).click() + wait.until(EC.url_to_be(LOGIN_URL)) + + wait.until(EC.visibility_of_element_located(LoginPageLocators.EMAIL_INPUT)).send_keys(email) + driver.find_element(*LoginPageLocators.PASSWORD_INPUT).send_keys(password) + driver.find_element(*LoginPageLocators.LOGIN_BUTTON).click() + + wait.until(EC.url_to_be(BASE_URL + "/")) + assert driver.current_url == BASE_URL + "/" + + def test_login_via_forgot_password_link(self, driver): + wait = WebDriverWait(driver, 5) + + email, password = register_and_get_credentials(driver) + + driver.get(FORGOT_PASSWORD_URL) + + wait.until(EC.element_to_be_clickable(ForgotPasswordPageLocators.LOGIN_LINK)).click() + wait.until(EC.url_to_be(LOGIN_URL)) + + wait.until(EC.visibility_of_element_located(LoginPageLocators.EMAIL_INPUT)).send_keys(email) + driver.find_element(*LoginPageLocators.PASSWORD_INPUT).send_keys(password) + driver.find_element(*LoginPageLocators.LOGIN_BUTTON).click() + + wait.until(EC.url_to_be(BASE_URL + "/")) + assert driver.current_url == BASE_URL + "/" \ No newline at end of file diff --git a/tests/test_personal_account.py b/tests/test_personal_account.py new file mode 100644 index 000000000..3b2ae01a3 --- /dev/null +++ b/tests/test_personal_account.py @@ -0,0 +1,87 @@ +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC + +from helpers import BASE_URL, LOGIN_URL, REGISTER_URL, generate_email, generate_password +from locators.locators import MainPageLocators, LoginPageLocators, RegisterPageLocators, ProfilePageLocators + + +def register_and_login(driver): + wait = WebDriverWait(driver, 7) + + email = generate_email() + password = generate_password() + + driver.get(REGISTER_URL) + + wait.until(EC.visibility_of_element_located(RegisterPageLocators.NAME_INPUT)).send_keys("Test User") + driver.find_element(*RegisterPageLocators.EMAIL_INPUT).send_keys(email) + driver.find_element(*RegisterPageLocators.PASSWORD_INPUT).send_keys(password) + driver.find_element(*RegisterPageLocators.REGISTER_BUTTON).click() + + wait.until(EC.url_to_be(LOGIN_URL)) + + wait.until(EC.visibility_of_element_located(LoginPageLocators.EMAIL_INPUT)).send_keys(email) + driver.find_element(*LoginPageLocators.PASSWORD_INPUT).send_keys(password) + driver.find_element(*LoginPageLocators.LOGIN_BUTTON).click() + + wait.until(EC.visibility_of_element_located(MainPageLocators.PERSONAL_ACCOUNT_LINK)) + + +class TestPersonalAccount: + + def test_navigate_to_profile(self, driver): + wait = WebDriverWait(driver, 7) + + register_and_login(driver) + + current_url = driver.current_url + + wait.until(EC.element_to_be_clickable(MainPageLocators.PERSONAL_ACCOUNT_LINK)).click() + wait.until(EC.url_changes(current_url)) + + assert "/account" in driver.current_url + + def test_navigate_to_constructor_via_link(self, driver): + wait = WebDriverWait(driver, 7) + + register_and_login(driver) + + wait.until(EC.element_to_be_clickable(MainPageLocators.PERSONAL_ACCOUNT_LINK)).click() + wait.until(EC.visibility_of_element_located(ProfilePageLocators.LOGOUT_BUTTON)) + + current_url = driver.current_url + + wait.until(EC.element_to_be_clickable(MainPageLocators.CONSTRUCTOR_LINK)).click() + wait.until(EC.url_changes(current_url)) + + assert driver.current_url == BASE_URL + "/" + + def test_navigate_to_constructor_via_logo(self, driver): + wait = WebDriverWait(driver, 7) + + register_and_login(driver) + + wait.until(EC.element_to_be_clickable(MainPageLocators.PERSONAL_ACCOUNT_LINK)).click() + wait.until(EC.visibility_of_element_located(ProfilePageLocators.LOGOUT_BUTTON)) + + current_url = driver.current_url + + wait.until(EC.element_to_be_clickable(MainPageLocators.LOGO)).click() + wait.until(EC.url_changes(current_url)) + + assert driver.current_url == BASE_URL + "/" + + def test_logout(self, driver): + wait = WebDriverWait(driver, 7) + + register_and_login(driver) + + wait.until(EC.element_to_be_clickable(MainPageLocators.PERSONAL_ACCOUNT_LINK)).click() + wait.until(EC.visibility_of_element_located(ProfilePageLocators.LOGOUT_BUTTON)) + + current_url = driver.current_url + + wait.until(EC.element_to_be_clickable(ProfilePageLocators.LOGOUT_BUTTON)).click() + wait.until(EC.url_changes(current_url)) + + assert "/login" in driver.current_url \ No newline at end of file diff --git a/tests/test_registration.py b/tests/test_registration.py new file mode 100644 index 000000000..47dcbd89d --- /dev/null +++ b/tests/test_registration.py @@ -0,0 +1,40 @@ +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC + +from helpers import REGISTER_URL, LOGIN_URL, generate_email, generate_password +from locators.locators import RegisterPageLocators + + +class TestRegistration: + + def test_successful_registration(self, driver): + wait = WebDriverWait(driver, 5) + + driver.get(REGISTER_URL) + + email = generate_email() + password = generate_password() + + wait.until(EC.element_to_be_clickable(RegisterPageLocators.NAME_INPUT)).send_keys("Test User") + driver.find_element(*RegisterPageLocators.EMAIL_INPUT).send_keys(email) + driver.find_element(*RegisterPageLocators.PASSWORD_INPUT).send_keys(password) + driver.find_element(*RegisterPageLocators.REGISTER_BUTTON).click() + + wait.until(EC.url_to_be(LOGIN_URL)) + assert driver.current_url == LOGIN_URL + + def test_registration_with_invalid_password(self, driver): + wait = WebDriverWait(driver, 5) + + driver.get(REGISTER_URL) + + wait.until(EC.element_to_be_clickable(RegisterPageLocators.NAME_INPUT)).send_keys("Test User") + driver.find_element(*RegisterPageLocators.EMAIL_INPUT).send_keys(generate_email()) + driver.find_element(*RegisterPageLocators.PASSWORD_INPUT).send_keys("123") + driver.find_element(*RegisterPageLocators.REGISTER_BUTTON).click() + + error = wait.until( + EC.visibility_of_element_located(RegisterPageLocators.PASSWORD_ERROR) + ) + + assert error.is_displayed() \ No newline at end of file From a5243f38e1cfb152db8d07e0bcf7a796af34b615 Mon Sep 17 00:00:00 2001 From: Anastasia Nogovitcina Date: Thu, 2 Apr 2026 14:40:57 +0100 Subject: [PATCH 2/3] corrected --- conftest.py | 47 +++++++++++++++++++- locators/locators.py | 81 ---------------------------------- test_data.py | 7 +++ tests/test_bun.py | 26 +++++------ tests/test_burger.py | 58 +++++++----------------- tests/test_constructor.py | 17 ------- tests/test_ingredient.py | 41 +++++++++-------- tests/test_login.py | 42 +++++++++--------- tests/test_personal_account.py | 52 ++++++++++++++-------- tests/test_registration.py | 20 ++++----- 10 files changed, 169 insertions(+), 222 deletions(-) delete mode 100644 locators/locators.py create mode 100644 test_data.py delete mode 100644 tests/test_constructor.py diff --git a/conftest.py b/conftest.py index 85f8d355d..22547294c 100644 --- a/conftest.py +++ b/conftest.py @@ -1,9 +1,54 @@ import pytest from selenium import webdriver +from unittest.mock import MagicMock + +from praktikum.burger import Burger +from praktikum.bun import Bun +from praktikum.ingredient import Ingredient +from praktikum.ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING + +from test_data import ( + BUN_PRICE, BUN_NAME, + SAUCE_PRICE, SAUCE_NAME, + FILLING_PRICE, FILLING_NAME +) @pytest.fixture def driver(): driver = webdriver.Chrome() yield driver - driver.quit() \ No newline at end of file + driver.quit() + + +@pytest.fixture +def mock_bun(): + bun = MagicMock(spec=Bun) + bun.get_name.return_value = BUN_NAME + bun.get_price.return_value = BUN_PRICE + return bun + + +@pytest.fixture +def mock_sauce(): + ingredient = MagicMock(spec=Ingredient) + ingredient.get_name.return_value = SAUCE_NAME + ingredient.get_price.return_value = SAUCE_PRICE + ingredient.get_type.return_value = INGREDIENT_TYPE_SAUCE + return ingredient + + +@pytest.fixture +def mock_filling(): + ingredient = MagicMock(spec=Ingredient) + ingredient.get_name.return_value = FILLING_NAME + ingredient.get_price.return_value = FILLING_PRICE + ingredient.get_type.return_value = INGREDIENT_TYPE_FILLING + return ingredient + + +@pytest.fixture +def burger_with_bun(mock_bun): + burger = Burger() + burger.set_buns(mock_bun) + return burger \ No newline at end of file diff --git a/locators/locators.py b/locators/locators.py deleted file mode 100644 index fb1333969..000000000 --- a/locators/locators.py +++ /dev/null @@ -1,81 +0,0 @@ -from selenium.webdriver.common.by import By - - -class MainPageLocators: - # Кнопка «Войти в аккаунт» в конструкторе (видна только неавторизованным) - LOGIN_BUTTON = (By.XPATH, "//button[text()='Войти в аккаунт']") - - # Ссылка «Личный Кабинет» в шапке (тег ) - PERSONAL_ACCOUNT_LINK = (By.XPATH, "//a[@href='/account']") - - # Ссылка «Конструктор» в шапке (тег ) - CONSTRUCTOR_LINK = (By.XPATH, "//a[@href='/'][.//p[contains(@class,'AppHeader_header__linkText')]]") - - # Логотип Stellar Burgers в шапке (div-обёртка с классом header__logo) - LOGO = (By.XPATH, "//div[contains(@class,'AppHeader_header__logo')]") - - # Вкладка «Булки» в конструкторе (кликабельный div с текстом внутри span) - BUNS_TAB = (By.XPATH, "//div[contains(@class,'tab_tab')]//span[text()='Булки']") - - # Вкладка «Соусы» в конструкторе - SAUCES_TAB = (By.XPATH, "//div[contains(@class,'tab_tab')]//span[text()='Соусы']") - - # Вкладка «Начинки» в конструкторе - FILLINGS_TAB = (By.XPATH, "//div[contains(@class,'tab_tab')]//span[text()='Начинки']") - - # Заголовок раздела «Булки» в списке ингредиентов (h2) - BUNS_HEADING = (By.XPATH, "//h2[text()='Булки']") - - # Заголовок раздела «Соусы» в списке ингредиентов (h2) - SAUCES_HEADING = (By.XPATH, "//h2[text()='Соусы']") - - # Заголовок раздела «Начинки» в списке ингредиентов (h2) - FILLINGS_HEADING = (By.XPATH, "//h2[text()='Начинки']") - - -class LoginPageLocators: - # Поле ввода email на странице входа (первый fieldset, оба поля имеют name="name") - EMAIL_INPUT = (By.XPATH, "//fieldset[1]//input") - - # Поле ввода пароля на странице входа (второй fieldset, name="Пароль") - PASSWORD_INPUT = (By.XPATH, "//input[@name='Пароль']") - - # Кнопка «Войти» на странице входа - LOGIN_BUTTON = (By.XPATH, "//button[text()='Войти']") - - # Ссылка «Зарегистрироваться» на странице входа (класс Auth_link) - REGISTER_LINK = (By.XPATH, "//a[@href='/register']") - - # Ссылка «Восстановить пароль» на странице входа - FORGOT_PASSWORD_LINK = (By.XPATH, "//a[@href='/forgot-password']") - - -class RegisterPageLocators: - # Поле «Имя» на странице регистрации (первый fieldset) - NAME_INPUT = (By.XPATH, "//fieldset[1]//input") - - # Поле «Email» на странице регистрации (второй fieldset) - EMAIL_INPUT = (By.XPATH, "//fieldset[2]//input") - - # Поле «Пароль» на странице регистрации (третий fieldset) - PASSWORD_INPUT = (By.XPATH, "//fieldset[3]//input") - - # Кнопка «Зарегистрироваться» - REGISTER_BUTTON = (By.XPATH, "//button[text()='Зарегистрироваться']") - - # Ссылка «Войти» на странице регистрации (ведёт на /login) - LOGIN_LINK = (By.XPATH, "//a[@href='/login']") - - # Сообщение об ошибке при некорректном пароле - PASSWORD_ERROR = (By.XPATH, "//p[text()='Некорректный пароль']") - - -class ForgotPasswordPageLocators: - # Ссылка «Войти» на странице восстановления пароля (ведёт на /login) - LOGIN_LINK = (By.XPATH, "//a[@href='/login']") - - -class ProfilePageLocators: - # Кнопка «Выйти» в боковом меню личного кабинета - LOGOUT_BUTTON = (By.XPATH, "//button[text()='Выход']") - diff --git a/test_data.py b/test_data.py new file mode 100644 index 000000000..29d6b537f --- /dev/null +++ b/test_data.py @@ -0,0 +1,7 @@ +BUN_PRICE = 100 +SAUCE_PRICE = 50 +FILLING_PRICE = 100 + +BUN_NAME = 'black bun' +SAUCE_NAME = 'hot sauce' +FILLING_NAME = 'cutlet' \ No newline at end of file diff --git a/tests/test_bun.py b/tests/test_bun.py index db4372a31..81cfa94b8 100644 --- a/tests/test_bun.py +++ b/tests/test_bun.py @@ -4,20 +4,20 @@ class TestBun: - @pytest.mark.parametrize('name, price', [ - ('black bun', 100), - ('white bun', 200.5), - ('red bun', 0), + @pytest.mark.parametrize('name', [ + 'black bun', + 'white bun', + 'red bun', ]) - def test_get_name(self, name, price): - bun = Bun(name, price) + def test_get_name(self, name): + bun = Bun(name, 100) assert bun.get_name() == name - @pytest.mark.parametrize('name, price', [ - ('black bun', 100), - ('white bun', 200.5), - ('red bun', 0), + @pytest.mark.parametrize('price', [ + 100, + 200.5, + 0, ]) - def test_get_price(self, name, price): - bun = Bun(name, price) - assert bun.get_price() == price + def test_get_price(self, price): + bun = Bun('test bun', price) + assert bun.get_price() == price \ No newline at end of file diff --git a/tests/test_burger.py b/tests/test_burger.py index c1bf2afd9..7a198aba6 100644 --- a/tests/test_burger.py +++ b/tests/test_burger.py @@ -1,42 +1,15 @@ import pytest from unittest.mock import MagicMock + from praktikum.burger import Burger from praktikum.bun import Bun from praktikum.ingredient import Ingredient -from praktikum.ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING - - -@pytest.fixture -def mock_bun(): - bun = MagicMock(spec=Bun) - bun.get_name.return_value = 'black bun' - bun.get_price.return_value = 100 - return bun - - -@pytest.fixture -def mock_sauce(): - ingredient = MagicMock(spec=Ingredient) - ingredient.get_name.return_value = 'hot sauce' - ingredient.get_price.return_value = 50 - ingredient.get_type.return_value = INGREDIENT_TYPE_SAUCE - return ingredient - - -@pytest.fixture -def mock_filling(): - ingredient = MagicMock(spec=Ingredient) - ingredient.get_name.return_value = 'cutlet' - ingredient.get_price.return_value = 100 - ingredient.get_type.return_value = INGREDIENT_TYPE_FILLING - return ingredient - +from praktikum.ingredient_types import INGREDIENT_TYPE_SAUCE -@pytest.fixture -def burger_with_bun(mock_bun): - burger = Burger() - burger.set_buns(mock_bun) - return burger +from test_data import ( + BUN_PRICE, BUN_NAME, + SAUCE_NAME +) class TestBurgerSetBuns: @@ -86,12 +59,14 @@ def test_move_ingredient(self, burger_with_bun, mock_sauce, mock_filling): class TestBurgerGetPrice: def test_get_price_bun_only(self, burger_with_bun): - assert burger_with_bun.get_price() == 200 + expected = BUN_PRICE * 2 + assert burger_with_bun.get_price() == expected def test_get_price_with_ingredients(self, burger_with_bun, mock_sauce, mock_filling): burger_with_bun.add_ingredient(mock_sauce) burger_with_bun.add_ingredient(mock_filling) - assert burger_with_bun.get_price() == 350 + expected = BUN_PRICE * 2 + mock_sauce.get_price() + mock_filling.get_price() + assert burger_with_bun.get_price() == expected @pytest.mark.parametrize('bun_price, ingredient_prices, expected', [ (100, [], 200), @@ -119,18 +94,19 @@ def test_get_price_parametrized(self, bun_price, ingredient_prices, expected): class TestBurgerGetReceipt: def test_get_receipt_contains_bun_name(self, burger_with_bun): - assert 'black bun' in burger_with_bun.get_receipt() + assert BUN_NAME in burger_with_bun.get_receipt() def test_get_receipt_contains_price(self, burger_with_bun): - assert 'Price: 200' in burger_with_bun.get_receipt() + expected_price = BUN_PRICE * 2 + assert f'Price: {expected_price}' in burger_with_bun.get_receipt() def test_get_receipt_contains_ingredient_name(self, burger_with_bun, mock_sauce): burger_with_bun.add_ingredient(mock_sauce) - assert 'hot sauce' in burger_with_bun.get_receipt() + assert SAUCE_NAME in burger_with_bun.get_receipt() def test_get_receipt_contains_ingredient_type(self, burger_with_bun, mock_sauce): burger_with_bun.add_ingredient(mock_sauce) - assert 'sauce' in burger_with_bun.get_receipt() + assert mock_sauce.get_type().lower() in burger_with_bun.get_receipt() def test_get_receipt_format(self, burger_with_bun, mock_sauce): burger_with_bun.add_ingredient(mock_sauce) @@ -138,5 +114,5 @@ def test_get_receipt_format(self, burger_with_bun, mock_sauce): lines = receipt.split('\n') - assert lines[0] == '(==== black bun ====)' - assert '(==== black bun ====)' in lines + assert lines[0] == f'(==== {BUN_NAME} ====)' + assert f'(==== {BUN_NAME} ====)' in lines \ No newline at end of file diff --git a/tests/test_constructor.py b/tests/test_constructor.py deleted file mode 100644 index 6a8648735..000000000 --- a/tests/test_constructor.py +++ /dev/null @@ -1,17 +0,0 @@ -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC - -from helpers import BASE_URL -from locators.locators import MainPageLocators - - -def test_navigate_to_buns(driver): - wait = WebDriverWait(driver, 5) - - driver.get(BASE_URL) - - heading = wait.until( - EC.visibility_of_element_located(MainPageLocators.BUNS_HEADING) - ) - - assert heading.is_displayed() \ No newline at end of file diff --git a/tests/test_ingredient.py b/tests/test_ingredient.py index cb8ebc9c5..821ca9aa2 100644 --- a/tests/test_ingredient.py +++ b/tests/test_ingredient.py @@ -1,32 +1,35 @@ import pytest from praktikum.ingredient import Ingredient -from praktikum.ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING +from praktikum.ingredient_types import ( + INGREDIENT_TYPE_SAUCE, + INGREDIENT_TYPE_FILLING +) class TestIngredient: - @pytest.mark.parametrize('ingredient_type, name, price', [ - (INGREDIENT_TYPE_SAUCE, 'hot sauce', 100), - (INGREDIENT_TYPE_FILLING, 'cutlet', 200), - (INGREDIENT_TYPE_SAUCE, 'sour cream', 50.5), + @pytest.mark.parametrize('name', [ + 'hot sauce', + 'cutlet', + 'sour cream', ]) - def test_get_name(self, ingredient_type, name, price): - ingredient = Ingredient(ingredient_type, name, price) + def test_get_name(self, name): + ingredient = Ingredient(INGREDIENT_TYPE_SAUCE, name, 100) assert ingredient.get_name() == name - @pytest.mark.parametrize('ingredient_type, name, price', [ - (INGREDIENT_TYPE_SAUCE, 'hot sauce', 100), - (INGREDIENT_TYPE_FILLING, 'cutlet', 200), - (INGREDIENT_TYPE_SAUCE, 'sour cream', 50.5), + @pytest.mark.parametrize('price', [ + 100, + 200, + 50.5, ]) - def test_get_price(self, ingredient_type, name, price): - ingredient = Ingredient(ingredient_type, name, price) + def test_get_price(self, price): + ingredient = Ingredient(INGREDIENT_TYPE_SAUCE, 'test', price) assert ingredient.get_price() == price - @pytest.mark.parametrize('ingredient_type, name, price', [ - (INGREDIENT_TYPE_SAUCE, 'hot sauce', 100), - (INGREDIENT_TYPE_FILLING, 'cutlet', 200), + @pytest.mark.parametrize('ingredient_type', [ + INGREDIENT_TYPE_SAUCE, + INGREDIENT_TYPE_FILLING, ]) - def test_get_type(self, ingredient_type, name, price): - ingredient = Ingredient(ingredient_type, name, price) - assert ingredient.get_type() == ingredient_type + def test_get_type(self, ingredient_type): + ingredient = Ingredient(ingredient_type, 'test', 100) + assert ingredient.get_type() == ingredient_type \ No newline at end of file diff --git a/tests/test_login.py b/tests/test_login.py index 1ae2c919a..ce712abb2 100644 --- a/tests/test_login.py +++ b/tests/test_login.py @@ -1,8 +1,8 @@ +from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from helpers import BASE_URL, LOGIN_URL, REGISTER_URL, FORGOT_PASSWORD_URL, generate_email, generate_password -from locators.locators import MainPageLocators, LoginPageLocators, RegisterPageLocators, ForgotPasswordPageLocators def register_and_get_credentials(driver): @@ -13,10 +13,10 @@ def register_and_get_credentials(driver): email = generate_email() password = generate_password() - wait.until(EC.element_to_be_clickable(RegisterPageLocators.NAME_INPUT)).send_keys("Test User") - driver.find_element(*RegisterPageLocators.EMAIL_INPUT).send_keys(email) - driver.find_element(*RegisterPageLocators.PASSWORD_INPUT).send_keys(password) - driver.find_element(*RegisterPageLocators.REGISTER_BUTTON).click() + wait.until(EC.element_to_be_clickable((By.XPATH, "//fieldset[1]//input"))).send_keys("Test User") + driver.find_element(By.XPATH, "//fieldset[2]//input").send_keys(email) + driver.find_element(By.XPATH, "//fieldset[3]//input").send_keys(password) + driver.find_element(By.XPATH, "//button[text()='Зарегистрироваться']").click() wait.until(EC.url_to_be(LOGIN_URL)) @@ -32,11 +32,11 @@ def test_login_via_main_button(self, driver): driver.get(BASE_URL) - wait.until(EC.element_to_be_clickable(MainPageLocators.LOGIN_BUTTON)).click() + wait.until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Войти в аккаунт']"))).click() - wait.until(EC.visibility_of_element_located(LoginPageLocators.EMAIL_INPUT)).send_keys(email) - driver.find_element(*LoginPageLocators.PASSWORD_INPUT).send_keys(password) - driver.find_element(*LoginPageLocators.LOGIN_BUTTON).click() + wait.until(EC.visibility_of_element_located((By.XPATH, "//fieldset[1]//input"))).send_keys(email) + driver.find_element(By.XPATH, "//input[@name='Пароль']").send_keys(password) + driver.find_element(By.XPATH, "//button[text()='Войти']").click() wait.until(EC.url_to_be(BASE_URL + "/")) assert driver.current_url == BASE_URL + "/" @@ -48,12 +48,12 @@ def test_login_via_personal_account_link(self, driver): driver.get(BASE_URL) - wait.until(EC.element_to_be_clickable(MainPageLocators.PERSONAL_ACCOUNT_LINK)).click() + wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/account']"))).click() wait.until(EC.url_to_be(LOGIN_URL)) - wait.until(EC.visibility_of_element_located(LoginPageLocators.EMAIL_INPUT)).send_keys(email) - driver.find_element(*LoginPageLocators.PASSWORD_INPUT).send_keys(password) - driver.find_element(*LoginPageLocators.LOGIN_BUTTON).click() + wait.until(EC.visibility_of_element_located((By.XPATH, "//fieldset[1]//input"))).send_keys(email) + driver.find_element(By.XPATH, "//input[@name='Пароль']").send_keys(password) + driver.find_element(By.XPATH, "//button[text()='Войти']").click() wait.until(EC.url_to_be(BASE_URL + "/")) assert driver.current_url == BASE_URL + "/" @@ -65,12 +65,12 @@ def test_login_via_register_page_link(self, driver): driver.get(REGISTER_URL) - wait.until(EC.element_to_be_clickable(RegisterPageLocators.LOGIN_LINK)).click() + wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/login']"))).click() wait.until(EC.url_to_be(LOGIN_URL)) - wait.until(EC.visibility_of_element_located(LoginPageLocators.EMAIL_INPUT)).send_keys(email) - driver.find_element(*LoginPageLocators.PASSWORD_INPUT).send_keys(password) - driver.find_element(*LoginPageLocators.LOGIN_BUTTON).click() + wait.until(EC.visibility_of_element_located((By.XPATH, "//fieldset[1]//input"))).send_keys(email) + driver.find_element(By.XPATH, "//input[@name='Пароль']").send_keys(password) + driver.find_element(By.XPATH, "//button[text()='Войти']").click() wait.until(EC.url_to_be(BASE_URL + "/")) assert driver.current_url == BASE_URL + "/" @@ -82,12 +82,12 @@ def test_login_via_forgot_password_link(self, driver): driver.get(FORGOT_PASSWORD_URL) - wait.until(EC.element_to_be_clickable(ForgotPasswordPageLocators.LOGIN_LINK)).click() + wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/login']"))).click() wait.until(EC.url_to_be(LOGIN_URL)) - wait.until(EC.visibility_of_element_located(LoginPageLocators.EMAIL_INPUT)).send_keys(email) - driver.find_element(*LoginPageLocators.PASSWORD_INPUT).send_keys(password) - driver.find_element(*LoginPageLocators.LOGIN_BUTTON).click() + wait.until(EC.visibility_of_element_located((By.XPATH, "//fieldset[1]//input"))).send_keys(email) + driver.find_element(By.XPATH, "//input[@name='Пароль']").send_keys(password) + driver.find_element(By.XPATH, "//button[text()='Войти']").click() wait.until(EC.url_to_be(BASE_URL + "/")) assert driver.current_url == BASE_URL + "/" \ No newline at end of file diff --git a/tests/test_personal_account.py b/tests/test_personal_account.py index 3b2ae01a3..336897747 100644 --- a/tests/test_personal_account.py +++ b/tests/test_personal_account.py @@ -1,8 +1,8 @@ +from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from helpers import BASE_URL, LOGIN_URL, REGISTER_URL, generate_email, generate_password -from locators.locators import MainPageLocators, LoginPageLocators, RegisterPageLocators, ProfilePageLocators def register_and_login(driver): @@ -13,18 +13,18 @@ def register_and_login(driver): driver.get(REGISTER_URL) - wait.until(EC.visibility_of_element_located(RegisterPageLocators.NAME_INPUT)).send_keys("Test User") - driver.find_element(*RegisterPageLocators.EMAIL_INPUT).send_keys(email) - driver.find_element(*RegisterPageLocators.PASSWORD_INPUT).send_keys(password) - driver.find_element(*RegisterPageLocators.REGISTER_BUTTON).click() + wait.until(EC.visibility_of_element_located((By.XPATH, "//fieldset[1]//input"))).send_keys("Test User") + driver.find_element(By.XPATH, "//fieldset[2]//input").send_keys(email) + driver.find_element(By.XPATH, "//fieldset[3]//input").send_keys(password) + driver.find_element(By.XPATH, "//button[text()='Зарегистрироваться']").click() wait.until(EC.url_to_be(LOGIN_URL)) - wait.until(EC.visibility_of_element_located(LoginPageLocators.EMAIL_INPUT)).send_keys(email) - driver.find_element(*LoginPageLocators.PASSWORD_INPUT).send_keys(password) - driver.find_element(*LoginPageLocators.LOGIN_BUTTON).click() + wait.until(EC.visibility_of_element_located((By.XPATH, "//fieldset[1]//input"))).send_keys(email) + driver.find_element(By.XPATH, "//input[@name='Пароль']").send_keys(password) + driver.find_element(By.XPATH, "//button[text()='Войти']").click() - wait.until(EC.visibility_of_element_located(MainPageLocators.PERSONAL_ACCOUNT_LINK)) + wait.until(EC.visibility_of_element_located((By.XPATH, "//a[@href='/account']"))) class TestPersonalAccount: @@ -36,7 +36,7 @@ def test_navigate_to_profile(self, driver): current_url = driver.current_url - wait.until(EC.element_to_be_clickable(MainPageLocators.PERSONAL_ACCOUNT_LINK)).click() + wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/account']"))).click() wait.until(EC.url_changes(current_url)) assert "/account" in driver.current_url @@ -46,12 +46,18 @@ def test_navigate_to_constructor_via_link(self, driver): register_and_login(driver) - wait.until(EC.element_to_be_clickable(MainPageLocators.PERSONAL_ACCOUNT_LINK)).click() - wait.until(EC.visibility_of_element_located(ProfilePageLocators.LOGOUT_BUTTON)) + wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/account']"))).click() + wait.until(EC.visibility_of_element_located((By.XPATH, "//button[text()='Выход']"))) current_url = driver.current_url - wait.until(EC.element_to_be_clickable(MainPageLocators.CONSTRUCTOR_LINK)).click() + # иногда перекрывается → скролл + constructor = wait.until( + EC.presence_of_element_located((By.XPATH, "//a[@href='/']")) + ) + driver.execute_script("arguments[0].scrollIntoView();", constructor) + + wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/']"))).click() wait.until(EC.url_changes(current_url)) assert driver.current_url == BASE_URL + "/" @@ -61,12 +67,20 @@ def test_navigate_to_constructor_via_logo(self, driver): register_and_login(driver) - wait.until(EC.element_to_be_clickable(MainPageLocators.PERSONAL_ACCOUNT_LINK)).click() - wait.until(EC.visibility_of_element_located(ProfilePageLocators.LOGOUT_BUTTON)) + wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/account']"))).click() + wait.until(EC.visibility_of_element_located((By.XPATH, "//button[text()='Выход']"))) current_url = driver.current_url - wait.until(EC.element_to_be_clickable(MainPageLocators.LOGO)).click() + logo = wait.until( + EC.presence_of_element_located((By.XPATH, "//div[contains(@class,'AppHeader_header__logo')]")) + ) + driver.execute_script("arguments[0].scrollIntoView();", logo) + + wait.until( + EC.element_to_be_clickable((By.XPATH, "//div[contains(@class,'AppHeader_header__logo')]")) + ).click() + wait.until(EC.url_changes(current_url)) assert driver.current_url == BASE_URL + "/" @@ -76,12 +90,12 @@ def test_logout(self, driver): register_and_login(driver) - wait.until(EC.element_to_be_clickable(MainPageLocators.PERSONAL_ACCOUNT_LINK)).click() - wait.until(EC.visibility_of_element_located(ProfilePageLocators.LOGOUT_BUTTON)) + wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/account']"))).click() + wait.until(EC.visibility_of_element_located((By.XPATH, "//button[text()='Выход']"))) current_url = driver.current_url - wait.until(EC.element_to_be_clickable(ProfilePageLocators.LOGOUT_BUTTON)).click() + wait.until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Выход']"))).click() wait.until(EC.url_changes(current_url)) assert "/login" in driver.current_url \ No newline at end of file diff --git a/tests/test_registration.py b/tests/test_registration.py index 47dcbd89d..c42a37960 100644 --- a/tests/test_registration.py +++ b/tests/test_registration.py @@ -1,8 +1,8 @@ +from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from helpers import REGISTER_URL, LOGIN_URL, generate_email, generate_password -from locators.locators import RegisterPageLocators class TestRegistration: @@ -15,10 +15,10 @@ def test_successful_registration(self, driver): email = generate_email() password = generate_password() - wait.until(EC.element_to_be_clickable(RegisterPageLocators.NAME_INPUT)).send_keys("Test User") - driver.find_element(*RegisterPageLocators.EMAIL_INPUT).send_keys(email) - driver.find_element(*RegisterPageLocators.PASSWORD_INPUT).send_keys(password) - driver.find_element(*RegisterPageLocators.REGISTER_BUTTON).click() + wait.until(EC.element_to_be_clickable((By.XPATH, "//fieldset[1]//input"))).send_keys("Test User") + driver.find_element(By.XPATH, "//fieldset[2]//input").send_keys(email) + driver.find_element(By.XPATH, "//fieldset[3]//input").send_keys(password) + driver.find_element(By.XPATH, "//button[text()='Зарегистрироваться']").click() wait.until(EC.url_to_be(LOGIN_URL)) assert driver.current_url == LOGIN_URL @@ -28,13 +28,13 @@ def test_registration_with_invalid_password(self, driver): driver.get(REGISTER_URL) - wait.until(EC.element_to_be_clickable(RegisterPageLocators.NAME_INPUT)).send_keys("Test User") - driver.find_element(*RegisterPageLocators.EMAIL_INPUT).send_keys(generate_email()) - driver.find_element(*RegisterPageLocators.PASSWORD_INPUT).send_keys("123") - driver.find_element(*RegisterPageLocators.REGISTER_BUTTON).click() + wait.until(EC.element_to_be_clickable((By.XPATH, "//fieldset[1]//input"))).send_keys("Test User") + driver.find_element(By.XPATH, "//fieldset[2]//input").send_keys(generate_email()) + driver.find_element(By.XPATH, "//fieldset[3]//input").send_keys("123") + driver.find_element(By.XPATH, "//button[text()='Зарегистрироваться']").click() error = wait.until( - EC.visibility_of_element_located(RegisterPageLocators.PASSWORD_ERROR) + EC.visibility_of_element_located((By.XPATH, "//p[text()='Некорректный пароль']")) ) assert error.is_displayed() \ No newline at end of file From 3c750a02a26a84efc438cea3fbe561234779daf5 Mon Sep 17 00:00:00 2001 From: Anastasia Nogovitcina Date: Sun, 5 Apr 2026 10:12:38 +0100 Subject: [PATCH 3/3] =?UTF-8?q?=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20?= =?UTF-8?q?=D0=BD=D0=B0=D0=B4=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B0=D0=BC?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bun.py | 15 ----- burger.py | 48 ---------------- database.py | 33 ----------- helpers.py | 20 ------- ingredient.py | 20 ------- ingredient_types.py | 7 --- locators/__init__.py | 0 tests/test_login.py | 93 ------------------------------ tests/test_personal_account.py | 101 --------------------------------- tests/test_registration.py | 40 ------------- 10 files changed, 377 deletions(-) delete mode 100644 bun.py delete mode 100644 burger.py delete mode 100644 database.py delete mode 100644 helpers.py delete mode 100644 ingredient.py delete mode 100644 ingredient_types.py delete mode 100644 locators/__init__.py delete mode 100644 tests/test_login.py delete mode 100644 tests/test_personal_account.py delete mode 100644 tests/test_registration.py diff --git a/bun.py b/bun.py deleted file mode 100644 index 5504bc1f4..000000000 --- a/bun.py +++ /dev/null @@ -1,15 +0,0 @@ -class Bun: - """ - Модель булочки для бургера. - Булочке можно дать название и назначить цену. - """ - - def __init__(self, name: str, price: float): - self.name = name - self.price = price - - def get_name(self) -> str: - return self.name - - def get_price(self) -> float: - return self.price diff --git a/burger.py b/burger.py deleted file mode 100644 index 2b3b6a88b..000000000 --- a/burger.py +++ /dev/null @@ -1,48 +0,0 @@ -from typing import List - -from praktikum.bun import Bun -from praktikum.ingredient import Ingredient - - -class Burger: - """ - Модель бургера. - Бургер состоит из булочек и ингредиентов (начинка или соус). - Ингредиенты можно перемещать и удалять. - Можно распечать чек с информацией о бургере. - """ - - def __init__(self): - self.bun = None - self.ingredients: List[Ingredient] = [] - - def set_buns(self, bun: Bun): - self.bun = bun - - def add_ingredient(self, ingredient: Ingredient): - self.ingredients.append(ingredient) - - def remove_ingredient(self, index: int): - del self.ingredients[index] - - def move_ingredient(self, index: int, new_index: int): - self.ingredients.insert(new_index, self.ingredients.pop(index)) - - def get_price(self) -> float: - price = self.bun.get_price() * 2 - - for ingredient in self.ingredients: - price += ingredient.get_price() - - return price - - def get_receipt(self) -> str: - receipt: List[str] = [f'(==== {self.bun.get_name()} ====)'] - - for ingredient in self.ingredients: - receipt.append(f'= {str(ingredient.get_type()).lower()} {ingredient.get_name()} =') - - receipt.append(f'(==== {self.bun.get_name()} ====)\n') - receipt.append(f'Price: {self.get_price()}') - - return '\n'.join(receipt) diff --git a/database.py b/database.py deleted file mode 100644 index 4c75baf71..000000000 --- a/database.py +++ /dev/null @@ -1,33 +0,0 @@ -from typing import List - -from praktikum.bun import Bun -from praktikum.ingredient import Ingredient -from praktikum.ingredient_types import INGREDIENT_TYPE_SAUCE, INGREDIENT_TYPE_FILLING - - -class Database: - """ - Класс с методами по работе с базой данных. - """ - - def __init__(self): - self.buns: List[Bun] = [] - self.ingredients: List[Ingredient] = [] - - self.buns.append(Bun("black bun", 100)) - self.buns.append(Bun("white bun", 200)) - self.buns.append(Bun("red bun", 300)) - - self.ingredients.append(Ingredient(INGREDIENT_TYPE_SAUCE, "hot sauce", 100)) - self.ingredients.append(Ingredient(INGREDIENT_TYPE_SAUCE, "sour cream", 200)) - self.ingredients.append(Ingredient(INGREDIENT_TYPE_SAUCE, "chili sauce", 300)) - - self.ingredients.append(Ingredient(INGREDIENT_TYPE_FILLING, "cutlet", 100)) - self.ingredients.append(Ingredient(INGREDIENT_TYPE_FILLING, "dinosaur", 200)) - self.ingredients.append(Ingredient(INGREDIENT_TYPE_FILLING, "sausage", 300)) - - def available_buns(self) -> List[Bun]: - return self.buns - - def available_ingredients(self) -> List[Ingredient]: - return self.ingredients diff --git a/helpers.py b/helpers.py deleted file mode 100644 index a9a87f0e3..000000000 --- a/helpers.py +++ /dev/null @@ -1,20 +0,0 @@ -import random -import string - -BASE_URL = "https://stellarburgers.education-services.ru" -LOGIN_URL = f"{BASE_URL}/login" -REGISTER_URL = f"{BASE_URL}/register" -FORGOT_PASSWORD_URL = f"{BASE_URL}/forgot-password" -PROFILE_URL = f"{BASE_URL}/account/profile" - - -def generate_email(): - """Генерирует уникальный email в формате имя_фамилия_когорта_XXX@домен.""" - digits = "".join(random.choices(string.digits, k=6)) - return f"test_testov_999_{digits}@yandex.ru" - - -def generate_password(length=8): - """Генерирует случайный пароль заданной длины (минимум 6 символов).""" - chars = string.ascii_letters + string.digits - return "".join(random.choices(chars, k=length)) diff --git a/ingredient.py b/ingredient.py deleted file mode 100644 index 0e50db8a2..000000000 --- a/ingredient.py +++ /dev/null @@ -1,20 +0,0 @@ -class Ingredient: - """ - Модель ингредиента. - Ингредиент: начинка или соус. - У ингредиента есть тип (начинка или соус), название и цена. - """ - - def __init__(self, ingredient_type: str, name: str, price: float): - self.type = ingredient_type - self.name = name - self.price = price - - def get_price(self) -> float: - return self.price - - def get_name(self) -> str: - return self.name - - def get_type(self) -> str: - return self.type diff --git a/ingredient_types.py b/ingredient_types.py deleted file mode 100644 index 34940ad5d..000000000 --- a/ingredient_types.py +++ /dev/null @@ -1,7 +0,0 @@ -""" -Перечисление с типами ингредиентов. -SAUCE – соус -FILLING – начинка -""" -INGREDIENT_TYPE_SAUCE = 'SAUCE' -INGREDIENT_TYPE_FILLING = 'FILLING' diff --git a/locators/__init__.py b/locators/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/test_login.py b/tests/test_login.py deleted file mode 100644 index ce712abb2..000000000 --- a/tests/test_login.py +++ /dev/null @@ -1,93 +0,0 @@ -from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC - -from helpers import BASE_URL, LOGIN_URL, REGISTER_URL, FORGOT_PASSWORD_URL, generate_email, generate_password - - -def register_and_get_credentials(driver): - wait = WebDriverWait(driver, 5) - - driver.get(REGISTER_URL) - - email = generate_email() - password = generate_password() - - wait.until(EC.element_to_be_clickable((By.XPATH, "//fieldset[1]//input"))).send_keys("Test User") - driver.find_element(By.XPATH, "//fieldset[2]//input").send_keys(email) - driver.find_element(By.XPATH, "//fieldset[3]//input").send_keys(password) - driver.find_element(By.XPATH, "//button[text()='Зарегистрироваться']").click() - - wait.until(EC.url_to_be(LOGIN_URL)) - - return email, password - - -class TestLogin: - - def test_login_via_main_button(self, driver): - wait = WebDriverWait(driver, 5) - - email, password = register_and_get_credentials(driver) - - driver.get(BASE_URL) - - wait.until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Войти в аккаунт']"))).click() - - wait.until(EC.visibility_of_element_located((By.XPATH, "//fieldset[1]//input"))).send_keys(email) - driver.find_element(By.XPATH, "//input[@name='Пароль']").send_keys(password) - driver.find_element(By.XPATH, "//button[text()='Войти']").click() - - wait.until(EC.url_to_be(BASE_URL + "/")) - assert driver.current_url == BASE_URL + "/" - - def test_login_via_personal_account_link(self, driver): - wait = WebDriverWait(driver, 5) - - email, password = register_and_get_credentials(driver) - - driver.get(BASE_URL) - - wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/account']"))).click() - wait.until(EC.url_to_be(LOGIN_URL)) - - wait.until(EC.visibility_of_element_located((By.XPATH, "//fieldset[1]//input"))).send_keys(email) - driver.find_element(By.XPATH, "//input[@name='Пароль']").send_keys(password) - driver.find_element(By.XPATH, "//button[text()='Войти']").click() - - wait.until(EC.url_to_be(BASE_URL + "/")) - assert driver.current_url == BASE_URL + "/" - - def test_login_via_register_page_link(self, driver): - wait = WebDriverWait(driver, 5) - - email, password = register_and_get_credentials(driver) - - driver.get(REGISTER_URL) - - wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/login']"))).click() - wait.until(EC.url_to_be(LOGIN_URL)) - - wait.until(EC.visibility_of_element_located((By.XPATH, "//fieldset[1]//input"))).send_keys(email) - driver.find_element(By.XPATH, "//input[@name='Пароль']").send_keys(password) - driver.find_element(By.XPATH, "//button[text()='Войти']").click() - - wait.until(EC.url_to_be(BASE_URL + "/")) - assert driver.current_url == BASE_URL + "/" - - def test_login_via_forgot_password_link(self, driver): - wait = WebDriverWait(driver, 5) - - email, password = register_and_get_credentials(driver) - - driver.get(FORGOT_PASSWORD_URL) - - wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/login']"))).click() - wait.until(EC.url_to_be(LOGIN_URL)) - - wait.until(EC.visibility_of_element_located((By.XPATH, "//fieldset[1]//input"))).send_keys(email) - driver.find_element(By.XPATH, "//input[@name='Пароль']").send_keys(password) - driver.find_element(By.XPATH, "//button[text()='Войти']").click() - - wait.until(EC.url_to_be(BASE_URL + "/")) - assert driver.current_url == BASE_URL + "/" \ No newline at end of file diff --git a/tests/test_personal_account.py b/tests/test_personal_account.py deleted file mode 100644 index 336897747..000000000 --- a/tests/test_personal_account.py +++ /dev/null @@ -1,101 +0,0 @@ -from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC - -from helpers import BASE_URL, LOGIN_URL, REGISTER_URL, generate_email, generate_password - - -def register_and_login(driver): - wait = WebDriverWait(driver, 7) - - email = generate_email() - password = generate_password() - - driver.get(REGISTER_URL) - - wait.until(EC.visibility_of_element_located((By.XPATH, "//fieldset[1]//input"))).send_keys("Test User") - driver.find_element(By.XPATH, "//fieldset[2]//input").send_keys(email) - driver.find_element(By.XPATH, "//fieldset[3]//input").send_keys(password) - driver.find_element(By.XPATH, "//button[text()='Зарегистрироваться']").click() - - wait.until(EC.url_to_be(LOGIN_URL)) - - wait.until(EC.visibility_of_element_located((By.XPATH, "//fieldset[1]//input"))).send_keys(email) - driver.find_element(By.XPATH, "//input[@name='Пароль']").send_keys(password) - driver.find_element(By.XPATH, "//button[text()='Войти']").click() - - wait.until(EC.visibility_of_element_located((By.XPATH, "//a[@href='/account']"))) - - -class TestPersonalAccount: - - def test_navigate_to_profile(self, driver): - wait = WebDriverWait(driver, 7) - - register_and_login(driver) - - current_url = driver.current_url - - wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/account']"))).click() - wait.until(EC.url_changes(current_url)) - - assert "/account" in driver.current_url - - def test_navigate_to_constructor_via_link(self, driver): - wait = WebDriverWait(driver, 7) - - register_and_login(driver) - - wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/account']"))).click() - wait.until(EC.visibility_of_element_located((By.XPATH, "//button[text()='Выход']"))) - - current_url = driver.current_url - - # иногда перекрывается → скролл - constructor = wait.until( - EC.presence_of_element_located((By.XPATH, "//a[@href='/']")) - ) - driver.execute_script("arguments[0].scrollIntoView();", constructor) - - wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/']"))).click() - wait.until(EC.url_changes(current_url)) - - assert driver.current_url == BASE_URL + "/" - - def test_navigate_to_constructor_via_logo(self, driver): - wait = WebDriverWait(driver, 7) - - register_and_login(driver) - - wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/account']"))).click() - wait.until(EC.visibility_of_element_located((By.XPATH, "//button[text()='Выход']"))) - - current_url = driver.current_url - - logo = wait.until( - EC.presence_of_element_located((By.XPATH, "//div[contains(@class,'AppHeader_header__logo')]")) - ) - driver.execute_script("arguments[0].scrollIntoView();", logo) - - wait.until( - EC.element_to_be_clickable((By.XPATH, "//div[contains(@class,'AppHeader_header__logo')]")) - ).click() - - wait.until(EC.url_changes(current_url)) - - assert driver.current_url == BASE_URL + "/" - - def test_logout(self, driver): - wait = WebDriverWait(driver, 7) - - register_and_login(driver) - - wait.until(EC.element_to_be_clickable((By.XPATH, "//a[@href='/account']"))).click() - wait.until(EC.visibility_of_element_located((By.XPATH, "//button[text()='Выход']"))) - - current_url = driver.current_url - - wait.until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Выход']"))).click() - wait.until(EC.url_changes(current_url)) - - assert "/login" in driver.current_url \ No newline at end of file diff --git a/tests/test_registration.py b/tests/test_registration.py deleted file mode 100644 index c42a37960..000000000 --- a/tests/test_registration.py +++ /dev/null @@ -1,40 +0,0 @@ -from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC - -from helpers import REGISTER_URL, LOGIN_URL, generate_email, generate_password - - -class TestRegistration: - - def test_successful_registration(self, driver): - wait = WebDriverWait(driver, 5) - - driver.get(REGISTER_URL) - - email = generate_email() - password = generate_password() - - wait.until(EC.element_to_be_clickable((By.XPATH, "//fieldset[1]//input"))).send_keys("Test User") - driver.find_element(By.XPATH, "//fieldset[2]//input").send_keys(email) - driver.find_element(By.XPATH, "//fieldset[3]//input").send_keys(password) - driver.find_element(By.XPATH, "//button[text()='Зарегистрироваться']").click() - - wait.until(EC.url_to_be(LOGIN_URL)) - assert driver.current_url == LOGIN_URL - - def test_registration_with_invalid_password(self, driver): - wait = WebDriverWait(driver, 5) - - driver.get(REGISTER_URL) - - wait.until(EC.element_to_be_clickable((By.XPATH, "//fieldset[1]//input"))).send_keys("Test User") - driver.find_element(By.XPATH, "//fieldset[2]//input").send_keys(generate_email()) - driver.find_element(By.XPATH, "//fieldset[3]//input").send_keys("123") - driver.find_element(By.XPATH, "//button[text()='Зарегистрироваться']").click() - - error = wait.until( - EC.visibility_of_element_located((By.XPATH, "//p[text()='Некорректный пароль']")) - ) - - assert error.is_displayed() \ No newline at end of file