From 6703b5cce6c5ea13b7b75af5580d424467d269e6 Mon Sep 17 00:00:00 2001 From: Aleksey Doludin Date: Thu, 24 Jul 2025 14:44:21 +0300 Subject: [PATCH 1/8] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=B2=D1=81=D0=B5=20=D1=82=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=BE=D0=B2=D1=8B=D0=B5=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 24 ++++++++++++ README.md | Bin 0 -> 2214 bytes confest.py | 29 ++++++++++++++ test_constructor.py | 37 ++++++++++++++++++ test_login.py | 46 ++++++++++++++++++++++ test_logout.py | 81 +++++++++++++++++++++++++++++++++++++++ test_navigation.py | 37 ++++++++++++++++++ test_personal_account.py | 16 ++++++++ test_registration.py | 69 +++++++++++++++++++++++++++++++++ 9 files changed, 339 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 confest.py create mode 100644 test_constructor.py create mode 100644 test_login.py create mode 100644 test_logout.py create mode 100644 test_navigation.py create mode 100644 test_personal_account.py create mode 100644 test_registration.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..98fe3c3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Игнорировать кэш Python +__pycache__/ +*.pyc +*.pyo +*.pyd + +# Игнорировать кэш pytest +.pytest_cache/ +.coverage +htmlcov/ + +# Игнорировать временные файлы тестов +*.tmp +*.testdb +*.log + +# Игнорировать локальные настройки +local_*.py +.env.test + +# Игнорировать файлы IDE +.idea/ +.vscode/ +*.swp \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..35948a8e58ae21ac662f6f825fc2fc172d5a5d0b GIT binary patch literal 2214 zcma)7O>fgs5cD}x{=<_v!;K5SfdfL~9ED&?P-It*gVbBolonK!h~6m_4qV-|rcRnT ze_`K0VrHM?G>xP5k`H^|?(EF$KDo3<_RtPwitm9vl*HI0No^mWxs2;I`H6?Qqzo`J zmZ{v?p*@uZK}W{+{vCeJ46x-gC-h}Ul50nD zrLA3~0DD1K1&B_#*A8}+x5t1!NBb;|{3wNTpu&D;U;2|gWXf48GdsASKkUUj3Lw+j zDpw}A>)FoAY(eu=d#@R{!(EWKF(wQ2p8_iPU zVS_nxT|*3TpU4%G&*=+E%CwQc*M`uKfemmek|~kY?Vi{$-8X0r?eG}>#QzaX$OWu` z11Rpy!j~)aRyeJ6^q6k2Bf_PhXbqUWaJQ1xq#y|u5^awMm>f8`O{fs{)`x(crY_tQaG5wy!C#Q|-W+l4I`3UhqG!9x=b)>h{Y#b;c~qkzth z4c^r%w9K4x=)&LB6Ne^cpAQzz_8$LWU2xvNAUCe9N>97JDAi80eFqrRj}4-01Hb{4 zcTnkRfSakIIO}c{bD2O{>;t&~1~(2o=7?GkQtq4%c7#FhlO|05F?gDgVuKs>Jr&0F zqT;=6cKt>#>hLbTLX>i-)BWc4%hk1v>lKR$;GA24SQ)>6Dd=id^Ry!Wogc*QW~a-v zg+w^ZEzI?SWy_YhdpOoKa9Kb*LtMF#U8}eYk1G`= 6, "Пароль должен быть ≥6 символов" + + submit_button = driver.find_element(By.XPATH, "//button[text()='Зарегистрироваться']") + submit_button.click() + + WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//h2[text()='Вход']"))) + + +def test_invalid_password_registration(driver, base_url): + driver.get(base_url) + + login_button = driver.find_element(By.XPATH, "//button[text()='Войти в аккаунт']") + login_button.click() + + WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//h2[text()='Вход']"))) + + register_button = driver.find_element(By.XPATH, "//a[text()='Зарегистрироваться']") + register_button.click() + + WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//h2[text()='Регистрация']"))) + + name_input = driver.find_element(By.XPATH, "//fieldset[1]//input") + email_input = driver.find_element(By.XPATH, "//fieldset[2]//input") + password_input = driver.find_element(By.XPATH, "//fieldset[3]//input") + + name_input.send_keys("Тестовое Имя") + email_input.send_keys(f"test{int(time.time())}@example.com") + password_input.send_keys("12345") + + assert len("12345") < 6, "Пароль должен быть <6 символов для этого теста" + + submit_button = driver.find_element(By.XPATH, "//button[text()='Зарегистрироваться']") + submit_button.click() + + error_message = WebDriverWait(driver, 10).until( + EC.visibility_of_element_located((By.XPATH, "//p[contains(text(), 'Некорректный пароль')]"))) + assert error_message.is_displayed() \ No newline at end of file From 7dc84f42550cb6f3a715b8bfd0db888099e05c98 Mon Sep 17 00:00:00 2001 From: Aleksey Doludin Date: Thu, 24 Jul 2025 15:06:38 +0300 Subject: [PATCH 2/8] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20README=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=20?= =?UTF-8?q?=D1=81=D0=BC=D0=B5=D0=BD=D0=BE=D0=B9=20=D0=B2=D0=B5=D1=82=D0=BA?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | Bin 2214 -> 2103 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index 35948a8e58ae21ac662f6f825fc2fc172d5a5d0b..02a18e69cd57e0282c684dac2fde66fac3146a2f 100644 GIT binary patch delta 378 zcmZ1`xLsg^{6vKSMy`p)O+eyDEF;(C2u5!pxr{LyNZw(UoGi;^4P-?#B>>5NOmZSz zC8@;SSCUf6fB`C{Y6ZXkQ^ zg$)u0QB2dkFiDjAT zi6xo&VB6eSK{gby8i7gm$!A!3fh?d$MX{UB%ccjEw_|J8h8kCtnw|;tI?O=qx<0aL c0CmZ*I|0c=cHzmT>_I@*DRv(qDanxv05jc^#Q*>R delta 481 zcmdlkuuO1*JR|Q!`2c2KF5Za+O?*I#t0c9!Bt9oUJu`1&qx@u9Mq`lVJqyiB}-pLP{QXD`AU6^>W`NHlCyDsbi^A=v%cd_|m-EZp9i;7msJR?&VkhkN~=$v z#mXxS*He&MRGgoem=m9voSa{phicqIxQ?RK^vvRtB7{9K_ibj=0IR;k z<^*=r1yGT-R5Fw>WH972a Date: Thu, 24 Jul 2025 15:29:07 +0300 Subject: [PATCH 3/8] Add PR trigger change --- README.md | Bin 2103 -> 2214 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index 02a18e69cd57e0282c684dac2fde66fac3146a2f..eb392d03583587396bd4457ffadc1ac7cb4303a7 100644 GIT binary patch delta 481 zcmdlkuuO1*JR|Q!`2c2KF5Za+O?*I#t0c9!Bt9oUJu`1&qx@u9Mq`lVJqyiB}-pLP{QXD`AU6^>W`NHlCyDsbi^A=v%cd_|m-EZp9i;7msJR?&VkhkN~=$v z#mXxS*He&MRGgoem=m9voSa{phicqIxQ?RK^vvRtB7{9K_ibj=0IR;k z<^*=r1yGv(dpnNH delta 378 zcmZ1`xLsg^{6vKSMy`p)O+eyDEF;(C2u5!pxr{LyNZw(UoGi;^4P-?#B>>5NOmZSz zC8@;SSCUf6fB`C{Y6ZXkQ^ zg$)u0QB2dkFiDjAT zi6xo&VB6eSK{gby8i7gm$!A!3fh?d$MX{UB%ccjEw_|J8h8kCtnw|;tI?O=qx<0aL c0CmZ*I|0c=cHzmT>_I@*DRv(qDanxv05jc^#Q*>R From b3db1a4de8611e355f6529e7ecc35171ef89796d Mon Sep 17 00:00:00 2001 From: Aleksey Doludin Date: Thu, 24 Jul 2025 15:38:50 +0300 Subject: [PATCH 4/8] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20README.md=20=D0=B8=D0=B7=20main?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | Bin 2106 -> 2686 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index f25432d134c9d234b0725bdc9e117727455a61ea..c08c9c23ac5e090303b57b3410d46b6a97ef3ecb 100644 GIT binary patch literal 2686 zcmbtWO>fgc5S_!GkT{S#tpf*6pu~wwnh!gUO9M)kNJyNk@Ksf++A2*e@#lf}X1!TE zaato(rS`6OcV^zaH?x0!H_gP1O=kLdW_W9vKqe+KDaNr0&2xDshnSBs$2Eb3cn-|m zOtCi7nH1y5bg_SKKA9fg%V*4VW{5MmW`Gra;ko>+<%iti|G9jV8@bl^mE2>r#&{*~ z&dvPyGpDf0SDr;XTBA2hUSHd+;EEy+9bzd)SR&w`GQy>0^GR=eW4z zJnpt4(7{^9Yhy3_cm>=vd93eX9YhGdb7A#mH z_q4c_E3jb+29Oc=n5i2xnKgxt7(8I^`@px2xe+W+@V?8r73?yfWZ>$bqaNej4$f!h z$g?8z2IdTylSM7f>%c5F_76;=yF7ol6<1FcjK^v-gePNIuzE~%M7>&_THLA1A-)`` z3U`%3&Fs^L*Xs*aa3B6VG@FPr0|uT^FA?)paWAg(F>R}8UmQ*)RT}XgHQ{$hbrovv zk1=)`A>U35p1sMDp&A@pW`;Y;Tq(x3dm6E;%KTHiLLikYTbOxrgLRWWF5p1|)L3_l zOxeb)SOKb0^SA^RKF(psT6P*?m3)k=jl7Cf<-o<;*wmUp{$T7m>@_2=P3Xj)N3#-{j z*yin`T6w;s?Bjfjos5h1ZHzyAmtj1-5qRaX|GF4h#cUmk5t*xG2bi-8;%VEBetLzMZ27uFw9y@fDmRRn+%!h+kN_+(|zsAAN!BKZ!?~K|ItRyAKS$D_?z0eWS6{4ZKCha#x}Ei zKk#QZBIelnp5629mXibj#S)uro%ZLvusP?6AToJTDs`&u&OxQwXm?uON~hU+e)PdT zbM`B%nS^p<@-IR<9wW*oc4H%d$}@4cwA2Zy-PtYG@A)-%AWLl_+^cph4ei)<=<9|8 z>SUZjs5cL5jXlNv39uKmuEJ!e5XGRue^O83r#MIgT@#!8{w8~~+u4(zJm;HCiQR4I zI?r-7%I|B3wyK9UM1GHC_|s7FPuAO=BQmJP7)~E)6;bXS zSJydu6h#9g1%Y;jFZeS$ODB+d_S2Qfe${{IOU1TWj!EDl2ZHqhQwVh3Vi4d1D~~!s^~tk3-Y^ z)ltygZ{}Yk{F$`eJh`sbiYqXb??t4HGbw*T~wnpqi6H1007ewJAC#tRTuq zx9d!#XFDb^7PsK!~ zS1OkyYX)4=8h{NfKV0mr$hZVs)wk6~r&g}Fl{6EDliH=)3M@@^qlKc0l~dR0Ls!JD P7i(;j3oj}O{*wC#MC(0g From bc9e1e3b2814b0851cc436df70301b33b6d8f5c4 Mon Sep 17 00:00:00 2001 From: Aleksey Doludin Date: Thu, 24 Jul 2025 15:47:32 +0300 Subject: [PATCH 5/8] =?UTF-8?q?=D0=AF=D0=B2=D0=BD=D0=BE=D0=B5=20=D0=B8?= =?UTF-8?q?=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=B0=D0=BA=D1=82=D0=B8=D0=B2=D0=B0=D1=86=D0=B8=D0=B8?= =?UTF-8?q?=20=D1=81=D1=80=D0=B0=D0=B2=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=B2=D0=B5=D1=82=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | Bin 2686 -> 2758 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index c08c9c23ac5e090303b57b3410d46b6a97ef3ecb..e437c4bc7a89c85f44d09567d1a81bcb0d518685 100644 GIT binary patch delta 80 zcmew-a!hnX9hZkPg93v-ixG=0iyez8ivoiMi#dx8kYx+T7GNm`cGs-9Txx&O9LhV From b520602e37bfb36ec5455a802ea5ce14be790f5a Mon Sep 17 00:00:00 2001 From: Aleksey Doludin Date: Mon, 28 Jul 2025 17:10:05 +0300 Subject: [PATCH 6/8] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BA=D0=BE=D0=B4=D0=B0=20=D1=81?= =?UTF-8?q?=D0=BE=D0=B3=D0=BB=D0=B0=D1=81=D0=BD=D0=BE=20=D0=B7=D0=B0=D0=BC?= =?UTF-8?q?=D0=B5=D1=87=D0=B0=D0=BD=D0=B8=D1=8F=D0=BC=20=D1=80=D0=B5=D0=B2?= =?UTF-8?q?=D1=8C=D1=8E=D0=B2=D0=B5=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- confest.py | 29 -------- conftest.py | 114 +++++++++++++++++++++++++++++ helpers.py | 13 ++++ locators.py | 8 +++ test_constructor.py | 71 ++++++++++++------ test_login.py | 78 +++++++++++--------- test_logout.py | 121 +++++++++++++++---------------- test_navigation.py | 67 ++++++++++------- test_personal_account.py | 30 ++++++-- test_registration.py | 152 +++++++++++++++++++++++---------------- urls.py | 1 + 11 files changed, 439 insertions(+), 245 deletions(-) delete mode 100644 confest.py create mode 100644 conftest.py create mode 100644 helpers.py create mode 100644 locators.py create mode 100644 urls.py diff --git a/confest.py b/confest.py deleted file mode 100644 index 899fafa..0000000 --- a/confest.py +++ /dev/null @@ -1,29 +0,0 @@ -import pytest -from selenium import webdriver - -@pytest.fixture(scope="function") -def driver(): - options = webdriver.ChromeOptions() - options.add_experimental_option('excludeSwitches', ['enable-logging']) - driver = webdriver.Chrome(options=options) - driver.maximize_window() - yield driver - driver.quit() - -@pytest.fixture -def base_url(): - """Базовый URL тестируемого приложения""" - return "https://stellarburgers.nomoreparties.site/" - -import time -import random - -@pytest.fixture -def test_credentials(): - """Тестовые учетные данные с уникальным email""" - random_part = int(time.time() * 1000) # Более уникальное значение - return { - "name": f"Тестовый Пользователь {random_part}", - "email": f"user_{random_part}@example.com", - "password": f"Pass{random_part % 10000}" # Более безопасный пароль - } \ No newline at end of file diff --git a/conftest.py b/conftest.py new file mode 100644 index 0000000..5017508 --- /dev/null +++ b/conftest.py @@ -0,0 +1,114 @@ +# conftest.py +import pytest +import time +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from urls import BASE_URL + +@pytest.fixture(scope="function") +def driver(): + """Фикстура для инициализации и завершения работы драйвера""" + driver = webdriver.Chrome() + yield driver + driver.quit() + +@pytest.fixture +def user_credentials(): + """Генерирует уникальные учетные данные пользователя""" + timestamp = int(time.time() * 1000) + return { + "name": f"TestUser{timestamp}", + "email": f"test{timestamp}@example.com", + "password": f"Password{timestamp % 10000}" + } + +@pytest.fixture +def registered_user(driver, user_credentials): + """Фикстура регистрации нового пользователя""" + driver.get(f"{BASE_URL}register") + + # Ожидаем загрузку формы регистрации + WebDriverWait(driver, 15).until( + EC.visibility_of_element_located((By.XPATH, "//h2[text()='Регистрация']")) + ) + + # Используем более надежные локаторы + name_input = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.XPATH, "//label[contains(text(), 'Имя')]/following-sibling::input")) + ) + email_input = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.XPATH, "//label[contains(text(), 'Email')]/following-sibling::input")) + ) + password_input = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.XPATH, "//input[@type='password']")) + ) + + # Заполнение формы + name_input.send_keys(user_credentials["name"]) + email_input.send_keys(user_credentials["email"]) + password_input.send_keys(user_credentials["password"]) + + # Отправка формы + driver.find_element(By.XPATH, "//button[text()='Зарегистрироваться']").click() + + # Ожидание перехода на страницу входа + WebDriverWait(driver, 15).until(EC.url_contains("login")) + return user_credentials + +@pytest.fixture +def login(driver, registered_user): + """Фикстура для выполнения входа зарегистрированного пользователя""" + def _login(): + driver.get(f"{BASE_URL}login") + + # Ожидаем загрузку формы входа + WebDriverWait(driver, 15).until( + EC.visibility_of_element_located((By.XPATH, "//h2[text()='Вход']")) + ) + + # Находим поля с более надежными локаторами + email_field = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.XPATH, "//input[@type='text' and contains(@name, 'name')]")) + ) + password_field = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.XPATH, "//input[@type='password']")) + ) + + # Заполняем поля + email_field.clear() + email_field.send_keys(registered_user["email"]) + password_field.clear() + password_field.send_keys(registered_user["password"]) + + # Кликаем кнопку входа + login_button = WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.XPATH, "//button[text()='Войти']")) + ) + login_button.click() + + # Ожидаем успешного входа + WebDriverWait(driver, 15).until( + EC.visibility_of_element_located((By.XPATH, "//button[text()='Оформить заказ']")) + ) + return _login + +@pytest.hookimpl(tryfirst=True, hookwrapper=True) +def pytest_runtest_makereport(item, call): + """Хук для создания скриншотов при падении тестов""" + outcome = yield + rep = outcome.get_result() + + if rep.when == "call" and rep.failed: + driver = item.funcargs.get('driver') + if driver is not None: + timestamp = time.strftime("%Y%m%d_%H%M%S") + driver.save_screenshot(f"failure_{item.name}_{timestamp}.png") + +from urls import BASE_URL # Убедитесь, что у вас есть файл urls.py с этим параметром + +@pytest.fixture +def base_url(): + """Фикстура для базового URL""" + return BASE_URL \ No newline at end of file diff --git a/helpers.py b/helpers.py new file mode 100644 index 0000000..52fee8e --- /dev/null +++ b/helpers.py @@ -0,0 +1,13 @@ +from selenium.webdriver.common.by import By +import time + +def login(driver, base_url, test_credentials): + driver.get(f"{base_url}login") + time.sleep(2) + + driver.find_element(By.XPATH, "//input[@name='name']").send_keys(test_credentials["email"]) + driver.find_element(By.XPATH, "//input[@type='password']").send_keys(test_credentials["password"]) + time.sleep(1) + + driver.find_element(By.XPATH, "//button[text()='Войти']").click() + time.sleep(2) \ No newline at end of file diff --git a/locators.py b/locators.py new file mode 100644 index 0000000..66d413d --- /dev/null +++ b/locators.py @@ -0,0 +1,8 @@ +from selenium.webdriver.common.by import By + + +class ConstructorPageLocators: + BUNS_TAB = (By.XPATH, "//span[text()='Булки']") + SAUCES_TAB = (By.XPATH, "//span[text()='Соусы']") + TOPPINGS_TAB = (By.XPATH, "//span[text()='Начинки']") + ACTIVE_TAB = (By.CSS_SELECTOR, ".tab_tab__1SPyG.tab_tab_type_current__2BEPc") \ No newline at end of file diff --git a/test_constructor.py b/test_constructor.py index b1ef1d8..8f78659 100644 --- a/test_constructor.py +++ b/test_constructor.py @@ -1,37 +1,64 @@ import pytest from selenium.webdriver.common.by import By -import time +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from urls import BASE_URL +from locators import ConstructorPageLocators class TestConstructorNavigation: - def test_buns_section(self, driver, base_url): - driver.get(base_url) - time.sleep(2) + """Тесты навигации между разделами конструктора""" + + def test_buns_section(self, driver): + """Тест переключения между разделами 'Булки' и 'Соусы'""" + driver.get(BASE_URL) - driver.find_element(By.XPATH, "//span[text()='Соусы']").click() - time.sleep(1) + # Проверка активной вкладки "Булки" по умолчанию + WebDriverWait(driver, 10).until( + EC.text_to_be_present_in_element(ConstructorPageLocators.ACTIVE_TAB, "Булки") + ) - driver.find_element(By.XPATH, "//span[text()='Булки']").click() - time.sleep(1) + # Переключение на вкладку "Соусы" + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable(ConstructorPageLocators.SAUCES_TAB) + ).click() - active_tab = driver.find_element(By.CSS_SELECTOR, ".tab_tab__1SPyG.tab_tab_type_current__2BEPc") - assert "Булки" in active_tab.text, "Раздел 'Булки' не активирован" + # Проверка активной вкладки "Соусы" + WebDriverWait(driver, 10).until( + EC.text_to_be_present_in_element(ConstructorPageLocators.ACTIVE_TAB, "Соусы") + ) + + # Возврат на вкладку "Булки" + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable(ConstructorPageLocators.BUNS_TAB) + ).click() + + # Финальная проверка активной вкладки "Булки" + WebDriverWait(driver, 10).until( + EC.text_to_be_present_in_element(ConstructorPageLocators.ACTIVE_TAB, "Булки") + ) - def test_sauces_section(self, driver, base_url): - driver.get(base_url) - time.sleep(2) + def test_sauces_section(self, driver): + """Тест переключения на раздел 'Соусы'""" + driver.get(BASE_URL) - driver.find_element(By.XPATH, "//span[text()='Соусы']").click() - time.sleep(1) + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable(ConstructorPageLocators.SAUCES_TAB) + ).click() - active_tab = driver.find_element(By.CSS_SELECTOR, ".tab_tab__1SPyG.tab_tab_type_current__2BEPc") + active_tab = WebDriverWait(driver, 10).until( + EC.visibility_of_element_located(ConstructorPageLocators.ACTIVE_TAB) + ) assert "Соусы" in active_tab.text, "Раздел 'Соусы' не активирован" - def test_toppings_section(self, driver, base_url): - driver.get(base_url) - time.sleep(2) + def test_toppings_section(self, driver): + """Тест переключения на раздел 'Начинки'""" + driver.get(BASE_URL) - driver.find_element(By.XPATH, "//span[text()='Начинки']").click() - time.sleep(1) + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable(ConstructorPageLocators.TOPPINGS_TAB) + ).click() - active_tab = driver.find_element(By.CSS_SELECTOR, ".tab_tab__1SPyG.tab_tab_type_current__2BEPc") + active_tab = WebDriverWait(driver, 10).until( + EC.visibility_of_element_located(ConstructorPageLocators.ACTIVE_TAB) + ) assert "Начинки" in active_tab.text, "Раздел 'Начинки' не активирован" \ No newline at end of file diff --git a/test_login.py b/test_login.py index 2253049..8fa4438 100644 --- a/test_login.py +++ b/test_login.py @@ -1,46 +1,56 @@ +# test_login.py import pytest from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from urls import BASE_URL class TestLogin: - def perform_login(self, driver, email, password, base_url): - try: - email_field = driver.find_element(By.XPATH, "//input[@name='name']") - email_field.clear() - email_field.send_keys(email) - - password_field = driver.find_element(By.XPATH, "//input[@type='password']") - password_field.clear() - password_field.send_keys(password) - - login_button = driver.find_element(By.XPATH, "//button[text()='Войти']") - login_button.click() - - assert base_url in driver.current_url - return True - except Exception as e: - print(f"Ошибка при входе: {str(e)}") - return False + """Тесты авторизации пользователя""" + + def perform_login(self, driver, email, password): + """Вспомогательный метод для выполнения входа""" + email_field = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.XPATH, "//input[@name='name']")) + ) + email_field.clear() + email_field.send_keys(email) + + password_field = driver.find_element(By.XPATH, "//input[@type='password']") + password_field.clear() + password_field.send_keys(password) + + login_button = driver.find_element(By.XPATH, "//button[text()='Войти']") + login_button.click() + + WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.XPATH, "//button[text()='Оформить заказ']")) + ) - def test_login_from_main_page_button(self, driver, base_url, test_credentials): - driver.get(base_url) + def test_login_from_main_page_button(self, driver, registered_user): + """Тест входа через кнопку на главной странице""" + driver.get(BASE_URL) driver.find_element(By.XPATH, "//button[text()='Войти в аккаунт']").click() - assert self.perform_login(driver, test_credentials["email"], test_credentials["password"], base_url), "Вход не выполнен" - assert base_url in driver.current_url + self.perform_login(driver, registered_user["email"], registered_user["password"]) + assert BASE_URL in driver.current_url - def test_login_from_personal_account_button(self, driver, base_url, test_credentials): - driver.get(base_url) + def test_login_from_personal_account_button(self, driver, registered_user): + """Тест входа через кнопку личного кабинета""" + driver.get(BASE_URL) driver.find_element(By.XPATH, "//a[@href='/account']").click() - assert self.perform_login(driver, test_credentials["email"], test_credentials["password"], base_url), "Вход не выполнен" - assert base_url in driver.current_url + self.perform_login(driver, registered_user["email"], registered_user["password"]) + assert BASE_URL in driver.current_url - def test_login_from_registration_form(self, driver, base_url, test_credentials): - driver.get(f"{base_url}register") + def test_login_from_registration_form(self, driver, registered_user): + """Тест входа через форму регистрации""" + driver.get(f"{BASE_URL}register") driver.find_element(By.XPATH, "//a[text()='Войти']").click() - assert self.perform_login(driver, test_credentials["email"], test_credentials["password"], base_url), "Вход не выполнен" - assert base_url in driver.current_url + self.perform_login(driver, registered_user["email"], registered_user["password"]) + assert BASE_URL in driver.current_url - def test_login_from_forgot_password_form(self, driver, base_url, test_credentials): - driver.get(f"{base_url}forgot-password") + def test_login_from_forgot_password_form(self, driver, registered_user): + """Тест входа через форму восстановления пароля""" + driver.get(f"{BASE_URL}forgot-password") driver.find_element(By.XPATH, "//a[text()='Войти']").click() - assert self.perform_login(driver, test_credentials["email"], test_credentials["password"], base_url), "Вход не выполнен" - assert base_url in driver.current_url \ No newline at end of file + self.perform_login(driver, registered_user["email"], registered_user["password"]) + assert BASE_URL in driver.current_url \ No newline at end of file diff --git a/test_logout.py b/test_logout.py index 637e8ca..0da713a 100644 --- a/test_logout.py +++ b/test_logout.py @@ -2,80 +2,73 @@ from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC +from urls import BASE_URL -def test_logout_from_account(driver, base_url, test_credentials): - try: - driver.get(f"{base_url}register") +class TestAccountLogout: + """Тесты выхода из аккаунта""" + + def test_logout_from_account(self, driver, login): + """Тест выхода из личного кабинета""" + login() # Выполняем вход через фикстуру + # Переходим в личный кабинет WebDriverWait(driver, 10).until( - EC.presence_of_element_located((By.XPATH, "//h2[contains(text(), 'Регистрация')]")) - ) - - name_field = WebDriverWait(driver, 10).until( - EC.presence_of_element_located((By.XPATH, "//label[contains(text(), 'Имя')]/following-sibling::input")) - ) - name_field.send_keys(test_credentials["name"]) - - email_field = WebDriverWait(driver, 10).until( - EC.presence_of_element_located((By.XPATH, "//label[contains(text(), 'Email')]/following-sibling::input")) - ) - email_field.send_keys(test_credentials["email"]) - - password_field = WebDriverWait(driver, 10).until( - EC.presence_of_element_located((By.XPATH, "//input[@type='password']")) - ) - password_field.send_keys(test_credentials["password"]) - - register_button = WebDriverWait(driver, 10).until( - EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Зарегистрироваться')]")) - ) - register_button.click() - - WebDriverWait(driver, 10).until( - EC.url_contains("login") - ) - - email_input = WebDriverWait(driver, 10).until( - EC.presence_of_element_located((By.XPATH, "//input[@type='text']")) - ) - email_input.send_keys(test_credentials["email"]) - - password_input = WebDriverWait(driver, 10).until( - EC.presence_of_element_located((By.XPATH, "//input[@type='password']")) - ) - password_input.send_keys(test_credentials["password"]) - - login_button = WebDriverWait(driver, 10).until( - EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Войти')]")) - ) - login_button.click() - - account_link = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "//a[contains(@href, '/account')]")) - ) - account_link.click() - - logout_button = WebDriverWait(driver, 10).until( - EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Выход')]")) - ) - logout_button.click() - + ).click() + + # Выходим из аккаунта WebDriverWait(driver, 10).until( - EC.presence_of_element_located((By.XPATH, "//button[contains(text(), 'Войти')]")) - ) + EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Выход')]")) + ).click() + # Проверяем, что произошел выход WebDriverWait(driver, 10).until( - lambda d: d.current_url == base_url or d.current_url == f"{base_url}login" + EC.presence_of_element_located((By.XPATH, "//button[contains(text(), 'Войти')]")) ) assert not driver.current_url.endswith("/account"), "После выхода не должно быть доступа к личному кабинету" + +class TestNavigationFromAccount: + """Тесты навигации из личного кабинета""" + + def test_navigate_to_constructor_via_button(self, driver, login): + """Тест перехода в конструктор через кнопку""" + login() + driver.get(f"{BASE_URL}account") - assert WebDriverWait(driver, 5).until( - EC.visibility_of_element_located((By.XPATH, "//button[contains(text(), 'Войти')]")) - ), "Кнопка 'Войти' должна отображаться после выхода" + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.XPATH, "//p[text()='Конструктор']")) + ).click() + + assert driver.current_url == BASE_URL, \ + f"После клика на 'Конструктор' ожидался переход на {BASE_URL}" - print("\nТест успешен: выход выполнен, кнопка 'Войти' отображается") + def test_navigate_to_constructor_via_logo(self, driver, login): + """Тест перехода в конструктор через логотип""" + login() + driver.get(f"{BASE_URL}account") + + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.CLASS_NAME, "AppHeader_header__logo__2D0X2")) + ).click() + + assert driver.current_url == BASE_URL, \ + f"После клика на логотип ожидался переход на {BASE_URL}" - except Exception as e: - driver.save_screenshot("logout_error.png") - pytest.fail(f"Тест упал с ошибкой: {str(e)}\nСкриншот сохранен как logout_error.png") \ No newline at end of file +class TestPersonalAccount: + """Тесты личного кабинета""" + + def test_personal_account_click(self, driver): + """Тест перехода в личный кабинет без авторизации""" + driver.get(BASE_URL) + + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.XPATH, "//a[@href='/account']")) + ).click() + + assert driver.current_url == f"{BASE_URL}login", \ + f"Ожидался переход на страницу входа" + + assert WebDriverWait(driver, 10).until( + EC.visibility_of_element_located((By.XPATH, "//h2[text()='Вход']")) + ).is_displayed(), "Заголовок 'Вход' не отображается" \ No newline at end of file diff --git a/test_navigation.py b/test_navigation.py index ed1d5a2..a15d809 100644 --- a/test_navigation.py +++ b/test_navigation.py @@ -1,37 +1,50 @@ import pytest from selenium.webdriver.common.by import By -import time +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from urls import BASE_URL # Импортируем BASE_URL из модуля urls.py class TestNavigationFromAccount: - def login(self, driver, base_url, test_credentials): - driver.get(f"{base_url}login") - time.sleep(2) + """Тесты навигации из личного кабинета""" + + def test_navigate_to_constructor_via_button(self, driver, login): + """Тест перехода в конструктор через кнопку""" + login() # Используем фикстуру login для авторизации - driver.find_element(By.XPATH, "//input[@name='name']").send_keys(test_credentials["email"]) - driver.find_element(By.XPATH, "//input[@type='password']").send_keys(test_credentials["password"]) - time.sleep(1) + # Переходим в личный кабинет + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.XPATH, "//a[contains(@href, '/account')]")) + ).click() - driver.find_element(By.XPATH, "//button[text()='Войти']").click() - time.sleep(2) - - def test_navigate_to_constructor_via_button(self, driver, base_url, test_credentials): - self.login(driver, base_url, test_credentials) - driver.get(f"{base_url}account") - time.sleep(2) - - driver.find_element(By.XPATH, "//p[text()='Конструктор']").click() - time.sleep(2) + # Кликаем на кнопку "Конструктор" + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.XPATH, "//p[text()='Конструктор']")) + ).click() - assert driver.current_url == base_url, \ - f"После клика на 'Конструктор' ожидался переход на {base_url}, но открыт {driver.current_url}" + # Проверяем переход на главную страницу + WebDriverWait(driver, 10).until( + EC.url_to_be(BASE_URL) + ) + assert driver.current_url == BASE_URL, \ + f"После клика на 'Конструктор' ожидался переход на {BASE_URL}" - def test_navigate_to_constructor_via_logo(self, driver, base_url, test_credentials): - self.login(driver, base_url, test_credentials) - driver.get(f"{base_url}account") - time.sleep(2) + def test_navigate_to_constructor_via_logo(self, driver, login): + """Тест перехода в конструктор через логотип""" + login() # Используем фикстуру login для авторизации + + # Переходим в личный кабинет + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.XPATH, "//a[contains(@href, '/account')]")) + ).click() - driver.find_element(By.CLASS_NAME, "AppHeader_header__logo__2D0X2").click() - time.sleep(2) + # Кликаем на логотип + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.CLASS_NAME, "AppHeader_header__logo__2D0X2")) + ).click() - assert driver.current_url == base_url, \ - f"После клика на логотип ожидался переход на {base_url}, но открыт {driver.current_url}" \ No newline at end of file + # Проверяем переход на главную страницу + WebDriverWait(driver, 10).until( + EC.url_to_be(BASE_URL) + ) + assert driver.current_url == BASE_URL, \ + f"После клика на логотип ожидался переход на {BASE_URL}" \ No newline at end of file diff --git a/test_personal_account.py b/test_personal_account.py index 29a1b3d..3e9e26f 100644 --- a/test_personal_account.py +++ b/test_personal_account.py @@ -1,16 +1,32 @@ import pytest from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from urls import BASE_URL # Импортируем BASE_URL из отдельного модуля class TestPersonalAccount: - def test_personal_account_click(self, driver, base_url): - driver.get(base_url) - - account_button = driver.find_element(By.XPATH, "//a[@href='/account']") + """Тесты для проверки личного кабинета""" + + def test_personal_account_click(self, driver): + """Тест перехода в личный кабинет без авторизации""" + # Переходим на главную страницу + driver.get(BASE_URL) + # Ожидаем и кликаем на кнопку личного кабинета + account_button = WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.XPATH, "//a[@href='/account']")) + ) account_button.click() - assert driver.current_url == f"{base_url}login", \ - f"Ожидался переход на {base_url}login, но открыт {driver.current_url}" + # Проверяем редирект на страницу входа + WebDriverWait(driver, 10).until( + EC.url_contains("login") + ) + assert driver.current_url == f"{BASE_URL}login", \ + f"Ожидался переход на {BASE_URL}login, получен {driver.current_url}" - login_title = driver.find_element(By.XPATH, "//h2[text()='Вход']") + # Проверяем отображение заголовка страницы входа + login_title = WebDriverWait(driver, 10).until( + EC.visibility_of_element_located((By.XPATH, "//h2[text()='Вход']")) + ) assert login_title.is_displayed(), "Заголовок 'Вход' не отображается" \ No newline at end of file diff --git a/test_registration.py b/test_registration.py index 5c5b44b..60abae8 100644 --- a/test_registration.py +++ b/test_registration.py @@ -1,69 +1,97 @@ import time +import pytest from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC -import pytest +from urls import BASE_URL # Используем BASE_URL из отдельного модуля +class TestRegistration: + """Тесты регистрации пользователя""" + + @pytest.fixture + def temp_credentials(self): + """Генерация уникальных учетных данных для теста""" + timestamp = int(time.time() * 1000) + return { + "name": f"User{timestamp}", + "email": f"user{timestamp}@example.com", + "password": f"Pass{timestamp % 10000}" + } -def test_successful_registration(driver, base_url, test_credentials): - driver.get(base_url) - - login_button = driver.find_element(By.XPATH, "//button[text()='Войти в аккаунт']") - login_button.click() - - WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//h2[text()='Вход']"))) - - register_button = driver.find_element(By.XPATH, "//a[text()='Зарегистрироваться']") - register_button.click() - - WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//h2[text()='Регистрация']"))) - - name_input = driver.find_element(By.XPATH, "//fieldset[1]//input") - email_input = driver.find_element(By.XPATH, "//fieldset[2]//input") - password_input = driver.find_element(By.XPATH, "//fieldset[3]//input") - - test_name = "Алексей" - name_input.send_keys(test_name) - email_input.send_keys(test_credentials["email"]) - password_input.send_keys(test_credentials["password"]) - - assert name_input.get_attribute("value") == test_name, "Имя должно быть заполнено" - assert "@" in test_credentials["email"], "Email должен содержать @" - assert "." in test_credentials["email"].split("@")[1], "Email должен содержать домен" - assert len(test_credentials["password"]) >= 6, "Пароль должен быть ≥6 символов" - - submit_button = driver.find_element(By.XPATH, "//button[text()='Зарегистрироваться']") - submit_button.click() - - WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//h2[text()='Вход']"))) + def test_successful_registration(self, driver, temp_credentials): + """Тест успешной регистрации нового пользователя""" + # Переходим на страницу регистрации + driver.get(f"{BASE_URL}register") + + # Ожидаем загрузку страницы + WebDriverWait(driver, 10).until( + EC.visibility_of_element_located((By.XPATH, "//h2[contains(text(), 'Регистрация')]")) + ) + + # Заполняем форму регистрации с явными ожиданиями + name_input = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.XPATH, "//label[contains(text(), 'Имя')]/following-sibling::input")) + ) + email_input = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.XPATH, "//label[contains(text(), 'Email')]/following-sibling::input")) + ) + password_input = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.XPATH, "//input[@type='password']")) + ) + + name_input.send_keys(temp_credentials["name"]) + email_input.send_keys(temp_credentials["email"]) + password_input.send_keys(temp_credentials["password"]) + + # Отправляем форму + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Зарегистрироваться')]")) + ).click() + + # Проверяем успешную регистрацию (редирект на страницу входа) + WebDriverWait(driver, 10).until( + EC.url_contains("login") + ) + assert "login" in driver.current_url, "После регистрации должен быть редирект на страницу входа" + + # Проверяем наличие заголовка "Вход" + assert WebDriverWait(driver, 10).until( + EC.visibility_of_element_located((By.XPATH, "//h2[contains(text(), 'Вход')]")) + ).is_displayed(), "Заголовок страницы входа не отображается" - -def test_invalid_password_registration(driver, base_url): - driver.get(base_url) - - login_button = driver.find_element(By.XPATH, "//button[text()='Войти в аккаунт']") - login_button.click() - - WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//h2[text()='Вход']"))) - - register_button = driver.find_element(By.XPATH, "//a[text()='Зарегистрироваться']") - register_button.click() - - WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//h2[text()='Регистрация']"))) - - name_input = driver.find_element(By.XPATH, "//fieldset[1]//input") - email_input = driver.find_element(By.XPATH, "//fieldset[2]//input") - password_input = driver.find_element(By.XPATH, "//fieldset[3]//input") - - name_input.send_keys("Тестовое Имя") - email_input.send_keys(f"test{int(time.time())}@example.com") - password_input.send_keys("12345") - - assert len("12345") < 6, "Пароль должен быть <6 символов для этого теста" - - submit_button = driver.find_element(By.XPATH, "//button[text()='Зарегистрироваться']") - submit_button.click() - - error_message = WebDriverWait(driver, 10).until( - EC.visibility_of_element_located((By.XPATH, "//p[contains(text(), 'Некорректный пароль')]"))) - assert error_message.is_displayed() \ No newline at end of file + def test_invalid_password_registration(self, driver): + """Тест регистрации с некорректным паролем""" + # Переходим на страницу регистрации + driver.get(f"{BASE_URL}register") + + # Ожидаем загрузку страницы + WebDriverWait(driver, 10).until( + EC.visibility_of_element_located((By.XPATH, "//h2[contains(text(), 'Регистрация')]")) + ) + + # Заполняем форму с некорректным паролем + name_input = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.XPATH, "//label[contains(text(), 'Имя')]/following-sibling::input")) + ) + email_input = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.XPATH, "//label[contains(text(), 'Email')]/following-sibling::input")) + ) + password_input = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.XPATH, "//input[@type='password']")) + ) + + name_input.send_keys("Тестовое Имя") + email_input.send_keys(f"test{int(time.time())}@example.com") + password_input.send_keys("12345") # Пароль короче 6 символов + + # Отправляем форму + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Зарегистрироваться')]")) + ).click() + + # Проверяем сообщение об ошибке + error_message = WebDriverWait(driver, 10).until( + EC.visibility_of_element_located((By.XPATH, "//p[contains(text(), 'Некорректный пароль')]")) + ) + assert error_message.is_displayed(), "Сообщение об ошибке не отображается" + assert "register" in driver.current_url, "При ошибке регистрации не должно быть редиректа" \ No newline at end of file diff --git a/urls.py b/urls.py new file mode 100644 index 0000000..dfa3118 --- /dev/null +++ b/urls.py @@ -0,0 +1 @@ +BASE_URL = "https://stellarburgers.nomoreparties.site/" \ No newline at end of file From 179273fe70911d3f60c072db783e3bbff9c2b84d Mon Sep 17 00:00:00 2001 From: Aleksey Doludin Date: Mon, 28 Jul 2025 17:32:25 +0300 Subject: [PATCH 7/8] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BA=D0=BE=D0=B4=D0=B0=20=D1=81?= =?UTF-8?q?=D0=BE=D0=B3=D0=BB=D0=B0=D1=81=D0=BD=D0=BE=20=D0=B7=D0=B0=D0=BC?= =?UTF-8?q?=D0=B5=D1=87=D0=B0=D0=BD=D0=B8=D1=8F=D0=BC=20=D1=80=D0=B5=D0=B2?= =?UTF-8?q?=D1=8C=D1=8E=D0=B2=D0=B5=D1=80=D0=B0=20=D0=B8=D1=82=D0=BE=D0=B3?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D1=8F=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conftest.py | 3 +-- test_login.py | 1 - test_navigation.py | 6 +++--- test_registration.py | 4 ++-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/conftest.py b/conftest.py index 5017508..943233b 100644 --- a/conftest.py +++ b/conftest.py @@ -106,9 +106,8 @@ def pytest_runtest_makereport(item, call): timestamp = time.strftime("%Y%m%d_%H%M%S") driver.save_screenshot(f"failure_{item.name}_{timestamp}.png") -from urls import BASE_URL # Убедитесь, что у вас есть файл urls.py с этим параметром +from urls import BASE_URL @pytest.fixture def base_url(): - """Фикстура для базового URL""" return BASE_URL \ No newline at end of file diff --git a/test_login.py b/test_login.py index 8fa4438..4deb428 100644 --- a/test_login.py +++ b/test_login.py @@ -1,4 +1,3 @@ -# test_login.py import pytest from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait diff --git a/test_navigation.py b/test_navigation.py index a15d809..a44d5f9 100644 --- a/test_navigation.py +++ b/test_navigation.py @@ -2,14 +2,14 @@ from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC -from urls import BASE_URL # Импортируем BASE_URL из модуля urls.py +from urls import BASE_URL class TestNavigationFromAccount: """Тесты навигации из личного кабинета""" def test_navigate_to_constructor_via_button(self, driver, login): """Тест перехода в конструктор через кнопку""" - login() # Используем фикстуру login для авторизации + login() # Переходим в личный кабинет WebDriverWait(driver, 10).until( @@ -30,7 +30,7 @@ def test_navigate_to_constructor_via_button(self, driver, login): def test_navigate_to_constructor_via_logo(self, driver, login): """Тест перехода в конструктор через логотип""" - login() # Используем фикстуру login для авторизации + login() # Переходим в личный кабинет WebDriverWait(driver, 10).until( diff --git a/test_registration.py b/test_registration.py index 60abae8..fddeaab 100644 --- a/test_registration.py +++ b/test_registration.py @@ -3,7 +3,7 @@ from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC -from urls import BASE_URL # Используем BASE_URL из отдельного модуля +from urls import BASE_URL class TestRegistration: """Тесты регистрации пользователя""" @@ -82,7 +82,7 @@ def test_invalid_password_registration(self, driver): name_input.send_keys("Тестовое Имя") email_input.send_keys(f"test{int(time.time())}@example.com") - password_input.send_keys("12345") # Пароль короче 6 символов + password_input.send_keys("12345") # Отправляем форму WebDriverWait(driver, 10).until( From 1b6cf3efb2e24399a8ff2a679347cfe7b8262d43 Mon Sep 17 00:00:00 2001 From: Aleksey Doludin Date: Tue, 29 Jul 2025 13:30:03 +0300 Subject: [PATCH 8/8] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2?= =?UTF-8?q?:=20=D0=B2=D1=8B=D0=BD=D0=B5=D1=81=20=D0=BB=D0=BE=D0=BA=D0=B0?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D1=8B=20=D0=B2=20=D0=BE=D1=82=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB?= =?UTF-8?q?=D1=8C(Locators),=20=D0=B2=D1=81=D0=BF=D0=BE=D0=BC=D0=BE=D0=B3?= =?UTF-8?q?=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5=20=D0=BC=D0=B5?= =?UTF-8?q?=D1=82=D0=BE=D0=B4=D1=8B=20=D0=B2=20helpers,=D1=83=D0=B1=D1=80?= =?UTF-8?q?=D0=B0=D0=BB=20=D1=84=D0=B8=D0=BA=D1=81=D1=82=D1=83=D1=80=D1=8B?= =?UTF-8?q?=20=D1=81=20=D0=BF=D1=80=D0=BE=D1=81=D1=82=D0=BE=D0=B9=20=D0=BB?= =?UTF-8?q?=D0=BE=D0=B3=D0=B8=D0=BA=D0=BE=D0=B9,=20=D0=BE=D1=82=D0=BA?= =?UTF-8?q?=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BB=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=B1=D0=B5?= =?UTF-8?q?=D0=B7=20time.sleep?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conftest.py | 7 ---- helpers.py | 70 +++++++++++++++++++++++++++++++----- locators.py | 49 ++++++++++++++++++++++--- test_constructor.py | 65 +++++++++++++++++++-------------- test_login.py | 58 ++++++++++++++---------------- test_logout.py | 26 +++++++++----- test_navigation.py | 13 +++---- test_personal_account.py | 9 ++--- test_registration.py | 78 ++++++++++++++++++---------------------- 9 files changed, 235 insertions(+), 140 deletions(-) diff --git a/conftest.py b/conftest.py index 943233b..fdaa5c0 100644 --- a/conftest.py +++ b/conftest.py @@ -96,7 +96,6 @@ def _login(): @pytest.hookimpl(tryfirst=True, hookwrapper=True) def pytest_runtest_makereport(item, call): - """Хук для создания скриншотов при падении тестов""" outcome = yield rep = outcome.get_result() @@ -105,9 +104,3 @@ def pytest_runtest_makereport(item, call): if driver is not None: timestamp = time.strftime("%Y%m%d_%H%M%S") driver.save_screenshot(f"failure_{item.name}_{timestamp}.png") - -from urls import BASE_URL - -@pytest.fixture -def base_url(): - return BASE_URL \ No newline at end of file diff --git a/helpers.py b/helpers.py index 52fee8e..c0848ea 100644 --- a/helpers.py +++ b/helpers.py @@ -1,13 +1,65 @@ from selenium.webdriver.common.by import By -import time +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC def login(driver, base_url, test_credentials): + wait = WebDriverWait(driver, 10) # Ожидание до 10 секунд + + # 1. Переход на страницу входа driver.get(f"{base_url}login") - time.sleep(2) - - driver.find_element(By.XPATH, "//input[@name='name']").send_keys(test_credentials["email"]) - driver.find_element(By.XPATH, "//input[@type='password']").send_keys(test_credentials["password"]) - time.sleep(1) - - driver.find_element(By.XPATH, "//button[text()='Войти']").click() - time.sleep(2) \ No newline at end of file + + # 2. Ожидание появления формы входа (проверяем заголовок "Вход") + wait.until( + EC.visibility_of_element_located((By.XPATH, "//h2[text()='Вход']")) + ) + + # 3. Ввод email и пароля + email_field = wait.until( + EC.visibility_of_element_located((By.XPATH, "//input[@name='name']")) + ) + email_field.send_keys(test_credentials["email"]) + + password_field = wait.until( + EC.visibility_of_element_located((By.XPATH, "//input[@type='password']")) + ) + password_field.send_keys(test_credentials["password"]) + + # 4. Клик по кнопке "Войти" + login_button = wait.until( + EC.element_to_be_clickable((By.XPATH, "//button[text()='Войти']")) + ) + login_button.click() + + # 5. Ожидание успешного входа (например, появления кнопки "Оформить заказ" на главной) + wait.until( + EC.visibility_of_element_located((By.XPATH, "//button[text()='Оформить заказ']")) + ) + + from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from locators import LoginPageLocators + +class LoginHelper: + @staticmethod + def perform_login(driver, email, password): + """Выполняет вход в систему""" + email_field = WebDriverWait(driver, 10).until( + EC.visibility_of_element_located(LoginPageLocators.EMAIL_INPUT) + ) + email_field.clear() + email_field.send_keys(email) + + password_field = WebDriverWait(driver, 10).until( + EC.visibility_of_element_located(LoginPageLocators.PASSWORD_INPUT) + ) + password_field.clear() + password_field.send_keys(password) + + login_button = WebDriverWait(driver, 10).until( + EC.element_to_be_clickable(LoginPageLocators.LOGIN_BUTTON) + ) + login_button.click() + + WebDriverWait(driver, 10).until( + EC.visibility_of_element_located(LoginPageLocators.ORDER_BUTTON) + ) \ No newline at end of file diff --git a/locators.py b/locators.py index 66d413d..ad0e28c 100644 --- a/locators.py +++ b/locators.py @@ -1,8 +1,49 @@ from selenium.webdriver.common.by import By +class MainPageLocators: + """Локаторы главной страницы""" + LOGIN_BUTTON = (By.XPATH, "//button[text()='Войти в аккаунт']") + ACCOUNT_BUTTON = (By.XPATH, "//a[@href='/account']") + LOGO = (By.CLASS_NAME, "AppHeader_header__logo__2D0X2") + + class ConstructorPageLocators: - BUNS_TAB = (By.XPATH, "//span[text()='Булки']") - SAUCES_TAB = (By.XPATH, "//span[text()='Соусы']") - TOPPINGS_TAB = (By.XPATH, "//span[text()='Начинки']") - ACTIVE_TAB = (By.CSS_SELECTOR, ".tab_tab__1SPyG.tab_tab_type_current__2BEPc") \ No newline at end of file + """Локаторы конструктора""" + CONSTRUCTOR_BUTTON = (By.XPATH, "//p[text()='Конструктор']") + BUNS_TAB = (By.XPATH, "//div[contains(@class, 'tab_tab')]//span[text()='Булки']/..") + SAUCES_TAB = (By.XPATH, "//div[contains(@class, 'tab_tab')]//span[text()='Соусы']/..") + TOPPINGS_TAB = (By.XPATH, "//div[contains(@class, 'tab_tab')]//span[text()='Начинки']/..") + ACTIVE_TAB = (By.XPATH, "//div[contains(@class, 'tab_tab_type_current')]/span") + BUNS_SECTION = (By.XPATH, "//h2[text()='Булки']/..") + SAUCES_SECTION = (By.XPATH, "//h2[text()='Соусы']/..") + TOPPINGS_SECTION = (By.XPATH, "//h2[text()='Начинки']/..") + + +class LoginPageLocators: + """Локаторы страницы входа""" + LOGIN_HEADER = (By.XPATH, "//h2[contains(text(), 'Вход')]") + EMAIL_INPUT = (By.XPATH, "//input[@name='name']") + PASSWORD_INPUT = (By.XPATH, "//input[@type='password']") + LOGIN_BUTTON = (By.XPATH, "//button[text()='Войти']") + ORDER_BUTTON = (By.XPATH, "//button[text()='Оформить заказ']") + + +class RegistrationPageLocators: + """Локаторы страницы регистрации""" + REGISTRATION_HEADER = (By.XPATH, "//h2[contains(text(), 'Регистрация')]") + NAME_INPUT = (By.XPATH, "//label[contains(text(), 'Имя')]/following-sibling::input") + EMAIL_INPUT = (By.XPATH, "//label[contains(text(), 'Email')]/following-sibling::input") + PASSWORD_INPUT = (By.XPATH, "//input[@type='password']") + SUBMIT_BUTTON = (By.XPATH, "//button[contains(text(), 'Зарегистрироваться')]") + PASSWORD_ERROR = (By.XPATH, "//p[contains(text(), 'Некорректный пароль')]") + LOGIN_LINK = (By.XPATH, "//a[text()='Войти']") + + +class ForgotPasswordLocators: + """Локаторы страницы восстановления пароля""" + LOGIN_LINK = (By.XPATH, "//a[text()='Войти']") + +class AccountPageLocators: + """Локаторы страницы личного кабинета""" + LOGOUT_BUTTON = (By.XPATH, "//button[contains(text(), 'Выход')]") \ No newline at end of file diff --git a/test_constructor.py b/test_constructor.py index 8f78659..694d052 100644 --- a/test_constructor.py +++ b/test_constructor.py @@ -1,64 +1,77 @@ import pytest -from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from urls import BASE_URL from locators import ConstructorPageLocators + class TestConstructorNavigation: """Тесты навигации между разделами конструктора""" - def test_buns_section(self, driver): + def test_buns_section_by_default(self, driver): + """Проверка, что по умолчанию активна вкладка 'Булки'""" + driver.get(BASE_URL) + + active_tab = WebDriverWait(driver, 10).until( + EC.visibility_of_element_located(ConstructorPageLocators.ACTIVE_TAB) + ) + assert active_tab.text == "Булки", f"Ожидалась активная вкладка 'Булки', но получили '{active_tab.text}'" + + def test_switch_between_buns_and_sauces(self, driver): """Тест переключения между разделами 'Булки' и 'Соусы'""" driver.get(BASE_URL) - # Проверка активной вкладки "Булки" по умолчанию - WebDriverWait(driver, 10).until( - EC.text_to_be_present_in_element(ConstructorPageLocators.ACTIVE_TAB, "Булки") + # Ожидаем загрузки конструктора + WebDriverWait(driver, 15).until( + EC.presence_of_element_located(ConstructorPageLocators.BUNS_SECTION) ) - # Переключение на вкладку "Соусы" + # Проверяем начальное состояние + active_tab = WebDriverWait(driver, 10).until( + EC.visibility_of_element_located(ConstructorPageLocators.ACTIVE_TAB) + ) + assert active_tab.text == "Булки", "По умолчанию должна быть активна вкладка 'Булки'" + + # Переключаемся на соусы WebDriverWait(driver, 10).until( EC.element_to_be_clickable(ConstructorPageLocators.SAUCES_TAB) ).click() - # Проверка активной вкладки "Соусы" - WebDriverWait(driver, 10).until( + # Ждем активации вкладки "Соусы" + WebDriverWait(driver, 15).until( EC.text_to_be_present_in_element(ConstructorPageLocators.ACTIVE_TAB, "Соусы") ) - # Возврат на вкладку "Булки" + # Возвращаемся на булки WebDriverWait(driver, 10).until( EC.element_to_be_clickable(ConstructorPageLocators.BUNS_TAB) ).click() - # Финальная проверка активной вкладки "Булки" - WebDriverWait(driver, 10).until( + # Ждем активации вкладки "Булки" с увеличенным таймаутом + WebDriverWait(driver, 15).until( EC.text_to_be_present_in_element(ConstructorPageLocators.ACTIVE_TAB, "Булки") ) - - def test_sauces_section(self, driver): - """Тест переключения на раздел 'Соусы'""" - driver.get(BASE_URL) + # Дополнительная проверка видимости раздела WebDriverWait(driver, 10).until( - EC.element_to_be_clickable(ConstructorPageLocators.SAUCES_TAB) - ).click() - - active_tab = WebDriverWait(driver, 10).until( - EC.visibility_of_element_located(ConstructorPageLocators.ACTIVE_TAB) - ) - assert "Соусы" in active_tab.text, "Раздел 'Соусы' не активирован" + EC.visibility_of_element_located(ConstructorPageLocators.BUNS_SECTION) + ) - def test_toppings_section(self, driver): + def test_switch_to_toppings_section(self, driver): """Тест переключения на раздел 'Начинки'""" driver.get(BASE_URL) - WebDriverWait(driver, 10).until( + toppings_tab = WebDriverWait(driver, 10).until( EC.element_to_be_clickable(ConstructorPageLocators.TOPPINGS_TAB) - ).click() + ) + toppings_tab.click() + + # Ждем появления раздела начинок + WebDriverWait(driver, 10).until( + EC.visibility_of_element_located(ConstructorPageLocators.TOPPINGS_SECTION) + ) active_tab = WebDriverWait(driver, 10).until( EC.visibility_of_element_located(ConstructorPageLocators.ACTIVE_TAB) ) - assert "Начинки" in active_tab.text, "Раздел 'Начинки' не активирован" \ No newline at end of file + assert active_tab.text == "Начинки", f"Ожидалась активная вкладка 'Начинки', но получили '{active_tab.text}'" \ No newline at end of file diff --git a/test_login.py b/test_login.py index 4deb428..223bf2c 100644 --- a/test_login.py +++ b/test_login.py @@ -1,55 +1,49 @@ import pytest -from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from urls import BASE_URL +from locators import (MainPageLocators, RegistrationPageLocators, ForgotPasswordLocators) +from helpers import LoginHelper class TestLogin: """Тесты авторизации пользователя""" - def perform_login(self, driver, email, password): - """Вспомогательный метод для выполнения входа""" - email_field = WebDriverWait(driver, 10).until( - EC.presence_of_element_located((By.XPATH, "//input[@name='name']")) - ) - email_field.clear() - email_field.send_keys(email) - - password_field = driver.find_element(By.XPATH, "//input[@type='password']") - password_field.clear() - password_field.send_keys(password) - - login_button = driver.find_element(By.XPATH, "//button[text()='Войти']") - login_button.click() - - WebDriverWait(driver, 10).until( - EC.presence_of_element_located((By.XPATH, "//button[text()='Оформить заказ']")) - ) - def test_login_from_main_page_button(self, driver, registered_user): """Тест входа через кнопку на главной странице""" driver.get(BASE_URL) - driver.find_element(By.XPATH, "//button[text()='Войти в аккаунт']").click() - self.perform_login(driver, registered_user["email"], registered_user["password"]) - assert BASE_URL in driver.current_url + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable(MainPageLocators.LOGIN_BUTTON) + ).click() + + LoginHelper.perform_login(driver, registered_user["email"], registered_user["password"]) + assert BASE_URL == driver.current_url def test_login_from_personal_account_button(self, driver, registered_user): """Тест входа через кнопку личного кабинета""" driver.get(BASE_URL) - driver.find_element(By.XPATH, "//a[@href='/account']").click() - self.perform_login(driver, registered_user["email"], registered_user["password"]) - assert BASE_URL in driver.current_url + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable(MainPageLocators.ACCOUNT_BUTTON) + ).click() + + LoginHelper.perform_login(driver, registered_user["email"], registered_user["password"]) + assert BASE_URL == driver.current_url def test_login_from_registration_form(self, driver, registered_user): """Тест входа через форму регистрации""" driver.get(f"{BASE_URL}register") - driver.find_element(By.XPATH, "//a[text()='Войти']").click() - self.perform_login(driver, registered_user["email"], registered_user["password"]) - assert BASE_URL in driver.current_url + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable(RegistrationPageLocators.LOGIN_LINK) + ).click() + + LoginHelper.perform_login(driver, registered_user["email"], registered_user["password"]) + assert BASE_URL == driver.current_url def test_login_from_forgot_password_form(self, driver, registered_user): """Тест входа через форму восстановления пароля""" driver.get(f"{BASE_URL}forgot-password") - driver.find_element(By.XPATH, "//a[text()='Войти']").click() - self.perform_login(driver, registered_user["email"], registered_user["password"]) - assert BASE_URL in driver.current_url \ No newline at end of file + WebDriverWait(driver, 10).until( + EC.element_to_be_clickable(ForgotPasswordLocators.LOGIN_LINK) + ).click() + + LoginHelper.perform_login(driver, registered_user["email"], registered_user["password"]) + assert BASE_URL == driver.current_url \ No newline at end of file diff --git a/test_logout.py b/test_logout.py index 0da713a..8837e08 100644 --- a/test_logout.py +++ b/test_logout.py @@ -1,33 +1,40 @@ import pytest -from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from urls import BASE_URL +from locators import ( + MainPageLocators, + ConstructorPageLocators, + LoginPageLocators, + AccountPageLocators +) + class TestAccountLogout: """Тесты выхода из аккаунта""" def test_logout_from_account(self, driver, login): """Тест выхода из личного кабинета""" - login() # Выполняем вход через фикстуру + login() # Переходим в личный кабинет WebDriverWait(driver, 10).until( - EC.element_to_be_clickable((By.XPATH, "//a[contains(@href, '/account')]")) + EC.element_to_be_clickable(MainPageLocators.ACCOUNT_BUTTON) ).click() # Выходим из аккаунта WebDriverWait(driver, 10).until( - EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Выход')]")) + EC.element_to_be_clickable(AccountPageLocators.LOGOUT_BUTTON) ).click() # Проверяем, что произошел выход WebDriverWait(driver, 10).until( - EC.presence_of_element_located((By.XPATH, "//button[contains(text(), 'Войти')]")) + EC.presence_of_element_located(LoginPageLocators.LOGIN_BUTTON) ) assert not driver.current_url.endswith("/account"), "После выхода не должно быть доступа к личному кабинету" + class TestNavigationFromAccount: """Тесты навигации из личного кабинета""" @@ -37,7 +44,7 @@ def test_navigate_to_constructor_via_button(self, driver, login): driver.get(f"{BASE_URL}account") WebDriverWait(driver, 10).until( - EC.element_to_be_clickable((By.XPATH, "//p[text()='Конструктор']")) + EC.element_to_be_clickable(ConstructorPageLocators.CONSTRUCTOR_BUTTON) ).click() assert driver.current_url == BASE_URL, \ @@ -49,12 +56,13 @@ def test_navigate_to_constructor_via_logo(self, driver, login): driver.get(f"{BASE_URL}account") WebDriverWait(driver, 10).until( - EC.element_to_be_clickable((By.CLASS_NAME, "AppHeader_header__logo__2D0X2")) + EC.element_to_be_clickable(MainPageLocators.LOGO) ).click() assert driver.current_url == BASE_URL, \ f"После клика на логотип ожидался переход на {BASE_URL}" + class TestPersonalAccount: """Тесты личного кабинета""" @@ -63,12 +71,12 @@ def test_personal_account_click(self, driver): driver.get(BASE_URL) WebDriverWait(driver, 10).until( - EC.element_to_be_clickable((By.XPATH, "//a[@href='/account']")) + EC.element_to_be_clickable(MainPageLocators.ACCOUNT_BUTTON) ).click() assert driver.current_url == f"{BASE_URL}login", \ f"Ожидался переход на страницу входа" assert WebDriverWait(driver, 10).until( - EC.visibility_of_element_located((By.XPATH, "//h2[text()='Вход']")) + EC.visibility_of_element_located(LoginPageLocators.LOGIN_HEADER) ).is_displayed(), "Заголовок 'Вход' не отображается" \ No newline at end of file diff --git a/test_navigation.py b/test_navigation.py index a44d5f9..79681fd 100644 --- a/test_navigation.py +++ b/test_navigation.py @@ -1,8 +1,9 @@ import pytest -from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC -from urls import BASE_URL +from urls import BASE_URL +from locators import MainPageLocators, ConstructorPageLocators, LoginPageLocators + class TestNavigationFromAccount: """Тесты навигации из личного кабинета""" @@ -13,12 +14,12 @@ def test_navigate_to_constructor_via_button(self, driver, login): # Переходим в личный кабинет WebDriverWait(driver, 10).until( - EC.element_to_be_clickable((By.XPATH, "//a[contains(@href, '/account')]")) + EC.element_to_be_clickable(MainPageLocators.ACCOUNT_BUTTON) ).click() # Кликаем на кнопку "Конструктор" WebDriverWait(driver, 10).until( - EC.element_to_be_clickable((By.XPATH, "//p[text()='Конструктор']")) + EC.element_to_be_clickable(ConstructorPageLocators.CONSTRUCTOR_BUTTON) ).click() # Проверяем переход на главную страницу @@ -34,12 +35,12 @@ def test_navigate_to_constructor_via_logo(self, driver, login): # Переходим в личный кабинет WebDriverWait(driver, 10).until( - EC.element_to_be_clickable((By.XPATH, "//a[contains(@href, '/account')]")) + EC.element_to_be_clickable(MainPageLocators.ACCOUNT_BUTTON) ).click() # Кликаем на логотип WebDriverWait(driver, 10).until( - EC.element_to_be_clickable((By.CLASS_NAME, "AppHeader_header__logo__2D0X2")) + EC.element_to_be_clickable(MainPageLocators.LOGO) ).click() # Проверяем переход на главную страницу diff --git a/test_personal_account.py b/test_personal_account.py index 3e9e26f..1fc0c83 100644 --- a/test_personal_account.py +++ b/test_personal_account.py @@ -1,8 +1,9 @@ import pytest -from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC -from urls import BASE_URL # Импортируем BASE_URL из отдельного модуля +from urls import BASE_URL +from locators import MainPageLocators, LoginPageLocators + class TestPersonalAccount: """Тесты для проверки личного кабинета""" @@ -14,7 +15,7 @@ def test_personal_account_click(self, driver): # Ожидаем и кликаем на кнопку личного кабинета account_button = WebDriverWait(driver, 10).until( - EC.element_to_be_clickable((By.XPATH, "//a[@href='/account']")) + EC.element_to_be_clickable(MainPageLocators.ACCOUNT_BUTTON) ) account_button.click() @@ -27,6 +28,6 @@ def test_personal_account_click(self, driver): # Проверяем отображение заголовка страницы входа login_title = WebDriverWait(driver, 10).until( - EC.visibility_of_element_located((By.XPATH, "//h2[text()='Вход']")) + EC.visibility_of_element_located(LoginPageLocators.LOGIN_HEADER) ) assert login_title.is_displayed(), "Заголовок 'Вход' не отображается" \ No newline at end of file diff --git a/test_registration.py b/test_registration.py index fddeaab..e4d2400 100644 --- a/test_registration.py +++ b/test_registration.py @@ -1,97 +1,89 @@ import time import pytest -from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC -from urls import BASE_URL +from urls import BASE_URL +from locators import RegistrationPageLocators, LoginPageLocators + class TestRegistration: """Тесты регистрации пользователя""" - - @pytest.fixture - def temp_credentials(self): - """Генерация уникальных учетных данных для теста""" - timestamp = int(time.time() * 1000) - return { - "name": f"User{timestamp}", - "email": f"user{timestamp}@example.com", - "password": f"Pass{timestamp % 10000}" - } - - def test_successful_registration(self, driver, temp_credentials): + + def test_successful_registration(self, driver, user_credentials): """Тест успешной регистрации нового пользователя""" # Переходим на страницу регистрации driver.get(f"{BASE_URL}register") - + # Ожидаем загрузку страницы WebDriverWait(driver, 10).until( - EC.visibility_of_element_located((By.XPATH, "//h2[contains(text(), 'Регистрация')]")) + EC.visibility_of_element_located(RegistrationPageLocators.REGISTRATION_HEADER) ) - - # Заполняем форму регистрации с явными ожиданиями + + # Заполняем форму регистрации name_input = WebDriverWait(driver, 10).until( - EC.presence_of_element_located((By.XPATH, "//label[contains(text(), 'Имя')]/following-sibling::input")) + EC.presence_of_element_located(RegistrationPageLocators.NAME_INPUT) ) email_input = WebDriverWait(driver, 10).until( - EC.presence_of_element_located((By.XPATH, "//label[contains(text(), 'Email')]/following-sibling::input")) + EC.presence_of_element_located(RegistrationPageLocators.EMAIL_INPUT) ) password_input = WebDriverWait(driver, 10).until( - EC.presence_of_element_located((By.XPATH, "//input[@type='password']")) + EC.presence_of_element_located(RegistrationPageLocators.PASSWORD_INPUT) ) - - name_input.send_keys(temp_credentials["name"]) - email_input.send_keys(temp_credentials["email"]) - password_input.send_keys(temp_credentials["password"]) - + + name_input.send_keys(user_credentials["name"]) + email_input.send_keys(user_credentials["email"]) + password_input.send_keys(user_credentials["password"]) + # Отправляем форму WebDriverWait(driver, 10).until( - EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Зарегистрироваться')]")) + EC.element_to_be_clickable(RegistrationPageLocators.SUBMIT_BUTTON) ).click() - + # Проверяем успешную регистрацию (редирект на страницу входа) WebDriverWait(driver, 10).until( EC.url_contains("login") ) assert "login" in driver.current_url, "После регистрации должен быть редирект на страницу входа" - + # Проверяем наличие заголовка "Вход" assert WebDriverWait(driver, 10).until( - EC.visibility_of_element_located((By.XPATH, "//h2[contains(text(), 'Вход')]")) + EC.visibility_of_element_located(LoginPageLocators.LOGIN_HEADER) ).is_displayed(), "Заголовок страницы входа не отображается" def test_invalid_password_registration(self, driver): """Тест регистрации с некорректным паролем""" # Переходим на страницу регистрации driver.get(f"{BASE_URL}register") - + # Ожидаем загрузку страницы WebDriverWait(driver, 10).until( - EC.visibility_of_element_located((By.XPATH, "//h2[contains(text(), 'Регистрация')]")) + EC.visibility_of_element_located(RegistrationPageLocators.REGISTRATION_HEADER) ) - + # Заполняем форму с некорректным паролем name_input = WebDriverWait(driver, 10).until( - EC.presence_of_element_located((By.XPATH, "//label[contains(text(), 'Имя')]/following-sibling::input")) + EC.presence_of_element_located(RegistrationPageLocators.NAME_INPUT) ) email_input = WebDriverWait(driver, 10).until( - EC.presence_of_element_located((By.XPATH, "//label[contains(text(), 'Email')]/following-sibling::input")) + EC.presence_of_element_located(RegistrationPageLocators.EMAIL_INPUT) ) password_input = WebDriverWait(driver, 10).until( - EC.presence_of_element_located((By.XPATH, "//input[@type='password']")) + EC.presence_of_element_located(RegistrationPageLocators.PASSWORD_INPUT) ) - + name_input.send_keys("Тестовое Имя") email_input.send_keys(f"test{int(time.time())}@example.com") - password_input.send_keys("12345") - + password_input.send_keys("12345") + # Отправляем форму WebDriverWait(driver, 10).until( - EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Зарегистрироваться')]")) + EC.element_to_be_clickable(RegistrationPageLocators.SUBMIT_BUTTON) ).click() - + # Проверяем сообщение об ошибке error_message = WebDriverWait(driver, 10).until( - EC.visibility_of_element_located((By.XPATH, "//p[contains(text(), 'Некорректный пароль')]")) + EC.visibility_of_element_located(RegistrationPageLocators.PASSWORD_ERROR) ) assert error_message.is_displayed(), "Сообщение об ошибке не отображается" - assert "register" in driver.current_url, "При ошибке регистрации не должно быть редиректа" \ No newline at end of file + assert "register" in driver.current_url, "При ошибке регистрации не должно быть редиректа" +