diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..92f250a --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# Python +__pycache__/ +*.pyc + +# Virtual environment +.venv/ +venv/ + +# Pytest +.pytest_cache/ + +# IDE +.idea/ +.vscode/ + +# OS +.DS_Store +Thumbs.db + +# Allure +allure-results/ diff --git a/README.md b/README.md index 93ca6f2..040a92c 100644 Binary files a/README.md and b/README.md differ diff --git a/conftest.py b/conftest.py new file mode 100644 index 0000000..21495fd --- /dev/null +++ b/conftest.py @@ -0,0 +1,29 @@ +import pytest +from selenium import webdriver +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.wait import WebDriverWait + +from curl import * +from locators import Locators +from data import Credentials + + +@pytest.fixture(scope="function") +def driver(): + driver = webdriver.Chrome() + driver.maximize_window() + yield driver + driver.quit() + +@pytest.fixture +def login(driver): + driver.get(MAIN_PAGE) + driver.find_element(*Locators.MAIN_LOGIN_BUTTON).click() + + WebDriverWait(driver, 5).until(EC.visibility_of_element_located(Locators.EMAIL)) + driver.find_element(*Locators.EMAIL).send_keys(Credentials.email) + driver.find_element(*Locators.PASSWORD).send_keys(Credentials.password) + driver.find_element(*Locators.LOGIN_BUTTON).click() + + WebDriverWait(driver, 5).until(EC.visibility_of_element_located(Locators.CONSTRUCTOR_TITLE)) + return driver diff --git a/curl.py b/curl.py new file mode 100644 index 0000000..f7a62ba --- /dev/null +++ b/curl.py @@ -0,0 +1,5 @@ +MAIN_PAGE = 'https://stellarburgers.education-services.ru/' #URL главной страницы +AUTH_PAGE = f'{MAIN_PAGE}login' #URL страницы авторизации +REG_PAGE = f'{MAIN_PAGE}register' #URL страницы регистрации +PROFILE_PAGE = f'{MAIN_PAGE}account/profile' #URL личного кабинета +FORGOT_PASSWORD_PAGE = f"{MAIN_PAGE}forgot-password" #URL страницы для восстановления пароля diff --git a/data.py b/data.py new file mode 100644 index 0000000..9a60ad0 --- /dev/null +++ b/data.py @@ -0,0 +1,4 @@ +class Credentials: + email = 'Alexander_Gerasimov_37_505@yandex.ru' + password = 'a15G51' + diff --git a/helper.py b/helper.py new file mode 100644 index 0000000..25ecf8b --- /dev/null +++ b/helper.py @@ -0,0 +1,19 @@ +from faker import Faker + +faker = Faker() + + +def generate_valid_registration_data(): + name = faker.name() + email = faker.email() + password = faker.password(length=6, special_chars=False, digits=True, upper_case=True, lower_case=True) + return name, email, password + + +def generate_registration_data_with_invalid_password(): + name = faker.name() + email = faker.email() + password = faker.password(length=3, special_chars=False, digits=True, upper_case=True, lower_case=True) + return name, email, password + + diff --git a/locators.py b/locators.py new file mode 100644 index 0000000..aabba64 --- /dev/null +++ b/locators.py @@ -0,0 +1,35 @@ +from selenium.webdriver.common.by import By + + +class Locators: + # Форма регистрации + NAME = (By.NAME, "name") # поле ввода Имя + EMAIL = (By.XPATH, "//label[text()='Email']/following-sibling::input") # поле ввода Имейл + PASSWORD = (By.NAME, "Пароль") # поле ввода Пароль + PASSWORD_ERROR = (By.XPATH, "//p[text()='Некорректный пароль']") # сообщение о вводе некорректного пароля + REGISTER_BUTTON = (By.XPATH, "//button[text()='Зарегистрироваться']") # кнопка Зарегистрироваться в форме регистрации + SIGN_BUTTON = (By.LINK_TEXT, "Войти") # кнопка Войти в форме регистрации + + # Форма авторизации + LOGIN_BUTTON = (By.XPATH, "//button[text()='Войти']") # кнопка Войти в форме авторизации + REGISTER_LINK = (By.LINK_TEXT, "Зарегистрироваться") # кнопка Зарегистрироваться в форме авторизации + RESTORE_BUTTON = (By.XPATH, "//button[text()='Восстановить']") # кнопка Восстановить пароль + + # Главная страница + MAIN_LOGIN_BUTTON = (By.XPATH, "//button[text()='Войти в аккаунт']") # кнопка Войти в аккаунт на главной странице + LOGO_BUTTON = (By.XPATH, "//div[@class='AppHeader_header__logo__2D0X2']") # логотип Stellar Burgers + + # Личный кабинет + PROFILE_BUTTON = (By.XPATH, "//p[text()='Личный Кабинет']") # кнопка Личный кабинет + LOGOUT_BUTTON = (By.XPATH, "//button[text()='Выход']") # кнопка Выход из профиля в личном кабинете + + # Конструктор + CONSTRUCTOR_BUTTON = (By.XPATH, ".//p[text() = 'Конструктор']") # вкладка Конструктор + CONSTRUCTOR_TITLE = (By.XPATH, "//h1[text()='Соберите бургер']") # заголовок Соберите бургер + BUNS_TAB = (By.XPATH, "//div[contains(@class,'tab_tab__')][.//span[normalize-space()='Булки']]") # секция Булки + SAUCES_TAB = (By.XPATH, "//div[contains(@class,'tab_tab__')][.//span[normalize-space()='Соусы']]") # секция Соусы + FILLINGS_TAB = (By.XPATH, "//div[contains(@class,'tab_tab__')][.//span[normalize-space()='Начинки']]") # секция Начинки + ACTIVE_TAB_TEXT = (By.XPATH, "//div[contains(@class,'tab_tab_type_current')]//span") # активная вкладка выбора + + + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..37a48f9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +selenium~=4.27.1 +pytest~=8.3.3 +requests~=2.32.3 +faker~=33.1.0 +webdriver_manager +allure-pytest \ No newline at end of file diff --git a/tests/test_constructor.py b/tests/test_constructor.py new file mode 100644 index 0000000..a6ee2da --- /dev/null +++ b/tests/test_constructor.py @@ -0,0 +1,33 @@ +import pytest +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC + +from curl import MAIN_PAGE +from locators import Locators + +class TestBurgerConstructor: + + @pytest.mark.parametrize("first_tab, second_tab, expected_name", [ + (Locators.FILLINGS_TAB, Locators.SAUCES_TAB, "Соусы"), + (Locators.SAUCES_TAB, Locators.FILLINGS_TAB, "Начинки"), + (Locators.FILLINGS_TAB, Locators.BUNS_TAB, "Булки"), + ]) + def test_burger_constructor_choosing_tabs(self, driver, first_tab, second_tab, expected_name): + driver.get(MAIN_PAGE) + wait = WebDriverWait(driver, 10) + + first = wait.until(EC.presence_of_element_located(first_tab)) + driver.execute_script("arguments[0].scrollIntoView({block:'center'});", first) + wait.until(EC.element_to_be_clickable(first)).click() + + second = wait.until(EC.presence_of_element_located(second_tab)) + driver.execute_script("arguments[0].scrollIntoView({block:'center'});", second) + wait.until(EC.element_to_be_clickable(second)).click() + + wait.until(lambda d: d.find_element(*Locators.ACTIVE_TAB_TEXT).text.strip() == expected_name) + assert driver.find_element(*Locators.ACTIVE_TAB_TEXT).text.strip() == expected_name + + + + + diff --git a/tests/test_login.py b/tests/test_login.py new file mode 100644 index 0000000..16661e5 --- /dev/null +++ b/tests/test_login.py @@ -0,0 +1,53 @@ +from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC + +from data import Credentials +from locators import Locators +from curl import * + + +class TestLogin: + + def test_login_main_page(self, driver): + driver.get(MAIN_PAGE) + driver.find_element(*Locators.MAIN_LOGIN_BUTTON).click() + + WebDriverWait(driver, 3).until(EC.visibility_of_element_located(Locators.EMAIL)).send_keys(Credentials.email) + driver.find_element(*Locators.PASSWORD).send_keys(Credentials.password) + driver.find_element(*Locators.LOGIN_BUTTON).click() + + WebDriverWait(driver, 3).until(EC.visibility_of_element_located(Locators.CONSTRUCTOR_TITLE)) + assert driver.current_url == MAIN_PAGE + + def test_login_profile_page(self, driver): + driver.get(MAIN_PAGE) + driver.find_element(*Locators.PROFILE_BUTTON).click() + + WebDriverWait(driver, 3).until(EC.visibility_of_element_located(Locators.EMAIL)).send_keys(Credentials.email) + driver.find_element(*Locators.PASSWORD).send_keys(Credentials.password) + driver.find_element(*Locators.LOGIN_BUTTON).click() + + WebDriverWait(driver, 3).until(EC.visibility_of_element_located(Locators.CONSTRUCTOR_TITLE)) + assert driver.current_url == MAIN_PAGE + + def test_login_registration_page(self, driver): + driver.get(REG_PAGE) + driver.find_element(*Locators.SIGN_BUTTON).click() + + WebDriverWait(driver, 3).until(EC.visibility_of_element_located(Locators.EMAIL)).send_keys(Credentials.email) + driver.find_element(*Locators.PASSWORD).send_keys(Credentials.password) + driver.find_element(*Locators.LOGIN_BUTTON).click() + + WebDriverWait(driver, 3).until(EC.visibility_of_element_located(Locators.CONSTRUCTOR_TITLE)) + assert driver.current_url == MAIN_PAGE + + def test_login_forgot_password_page(self, driver): + driver.get(FORGOT_PASSWORD_PAGE) + driver.find_element(*Locators.SIGN_BUTTON).click() + + WebDriverWait(driver, 3).until(EC.visibility_of_element_located(Locators.EMAIL)).send_keys(Credentials.email) + driver.find_element(*Locators.PASSWORD).send_keys(Credentials.password) + driver.find_element(*Locators.LOGIN_BUTTON).click() + + WebDriverWait(driver, 3).until(EC.visibility_of_element_located(Locators.CONSTRUCTOR_TITLE)) + assert driver.current_url == MAIN_PAGE diff --git a/tests/test_profile_page.py b/tests/test_profile_page.py new file mode 100644 index 0000000..4c9c9e0 --- /dev/null +++ b/tests/test_profile_page.py @@ -0,0 +1,34 @@ +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.wait import WebDriverWait + +from locators import Locators +from curl import * + + +class TestProfilePage: + + def test_go_to_profile_page(self, login): + WebDriverWait(login, 3).until(EC.element_to_be_clickable(Locators.PROFILE_BUTTON)).click() + WebDriverWait(login, 3).until(EC.visibility_of_element_located(Locators.LOGOUT_BUTTON)) + + assert login.current_url == PROFILE_PAGE + + def test_go_from_profile_page_to_constructor(self, login): + WebDriverWait(login, 3).until(EC.element_to_be_clickable(Locators.PROFILE_BUTTON)).click() + WebDriverWait(login, 3).until(EC.visibility_of_element_located(Locators.CONSTRUCTOR_BUTTON)).click() + + assert login.current_url == MAIN_PAGE + + def test_go_from_profile_page_to_main_click_logo(self, login): + WebDriverWait(login, 3).until(EC.element_to_be_clickable(Locators.PROFILE_BUTTON)).click() + WebDriverWait(login, 3).until(EC.visibility_of_element_located(Locators.LOGO_BUTTON)).click() + + assert login.current_url == MAIN_PAGE + + def test_logout_from_profile_page(self, login): + WebDriverWait(login, 3).until(EC.element_to_be_clickable(Locators.PROFILE_BUTTON)).click() + WebDriverWait(login, 3).until(EC.element_to_be_clickable(Locators.LOGOUT_BUTTON)).click() + WebDriverWait(login, 3).until(EC.visibility_of_element_located(Locators.LOGIN_BUTTON)) + + assert login.current_url == AUTH_PAGE + \ No newline at end of file diff --git a/tests/test_registration.py b/tests/test_registration.py new file mode 100644 index 0000000..609dd63 --- /dev/null +++ b/tests/test_registration.py @@ -0,0 +1,37 @@ +from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC + +from helper import * +from locators import Locators +from curl import * + + +class TestRegistration: + + def test_registration_success(self, driver): + driver.get(REG_PAGE) + name, email, password = generate_valid_registration_data() + + driver.find_element(*Locators.NAME).send_keys(name) + driver.find_element(*Locators.EMAIL).send_keys(email) + driver.find_element(*Locators.PASSWORD).send_keys(password) + + driver.find_element(*Locators.REGISTER_BUTTON).click() + + WebDriverWait(driver, 5).until(EC.url_contains("/login")) + assert driver.current_url == AUTH_PAGE + + + def test_registration_with_invalid_password_error(self, driver): + driver.get(REG_PAGE) + name, email, password = generate_registration_data_with_invalid_password() + + driver.find_element(*Locators.NAME).send_keys(name) + driver.find_element(*Locators.EMAIL).send_keys(email) + driver.find_element(*Locators.PASSWORD).send_keys(password) + + driver.find_element(*Locators.REGISTER_BUTTON).click() + + WebDriverWait(driver,3).until(EC.visibility_of_element_located(Locators.PASSWORD_ERROR)) + + assert driver.find_element(*Locators.PASSWORD_ERROR).text == "Некорректный пароль"