Initial commit
This commit is contained in:
commit
9795660e1f
43 changed files with 2757 additions and 0 deletions
0
tests/ui/__init__.py
Normal file
0
tests/ui/__init__.py
Normal file
130
tests/ui/conftest.py
Normal file
130
tests/ui/conftest.py
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
import logging
|
||||
import allure
|
||||
import pytest
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from datetime import datetime
|
||||
|
||||
from config.ui_config import UIConfig
|
||||
from tests.api.utils.api_client import APIClient
|
||||
from utils import waiters
|
||||
|
||||
from api.utils.api_client import APIClient
|
||||
from api.conftest import *
|
||||
from fixtures.data_fixtures import *
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@pytest.fixture
|
||||
def driver(request):
|
||||
"""Фикстура для браузера"""
|
||||
logger.info("=" * 50)
|
||||
logger.info("Initializing webdriver")
|
||||
|
||||
headless = UIConfig.BROWSER_HEADLESS
|
||||
browser_name = UIConfig.BROWSER_NAME
|
||||
fullscreen = UIConfig.BROWSER_FULLSCREEN
|
||||
|
||||
logger.info(f"Headless: {headless}")
|
||||
logger.info("Browser: {browser_name}")
|
||||
|
||||
logger.info("=" * 50)
|
||||
|
||||
if browser_name == "chrome":
|
||||
options = Options()
|
||||
if headless:
|
||||
options.add_argument("--headless")
|
||||
if fullscreen:
|
||||
options.add_argument("--start-maximized")
|
||||
options.add_argument("--no-sandbox")
|
||||
options.add_argument("--disable-dev-shm-usage")
|
||||
options.add_argument("--window-size=1920,1080")
|
||||
|
||||
driver = webdriver.Chrome(
|
||||
options=options
|
||||
)
|
||||
else:
|
||||
options = webdriver.FirefoxOptions()
|
||||
if headless:
|
||||
options.add_argument("--headless")
|
||||
if fullscreen:
|
||||
options.add_argument("--kiosk")
|
||||
options.add_argument("--width=1920")
|
||||
options.add_argument("--height=1080")
|
||||
driver = webdriver.Firefox(
|
||||
options=options
|
||||
)
|
||||
|
||||
driver.implicitly_wait(10)
|
||||
driver.maximize_window()
|
||||
|
||||
waiters.waiter = WebDriverWait(driver, 10)
|
||||
|
||||
def fin():
|
||||
if request.node.rep_call.failed:
|
||||
try:
|
||||
# Делаем скриншот при падении теста
|
||||
screenshot = driver.get_screenshot_as_png()
|
||||
allure.attach(
|
||||
screenshot,
|
||||
name=f"screenshot_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
|
||||
attachment_type=allure.attachment_type.PNG
|
||||
)
|
||||
|
||||
# Получаем текущий URL
|
||||
current_url = driver.current_url
|
||||
allure.attach(
|
||||
current_url,
|
||||
name="current_url",
|
||||
attachment_type=allure.attachment_type.TEXT
|
||||
)
|
||||
|
||||
# Получаем исходный код страницы
|
||||
page_source = driver.page_source
|
||||
allure.attach(
|
||||
page_source,
|
||||
name="page_source",
|
||||
attachment_type=allure.attachment_type.HTML
|
||||
)
|
||||
except:
|
||||
pass
|
||||
driver.quit()
|
||||
|
||||
request.addfinalizer(fin)
|
||||
|
||||
yield driver
|
||||
driver.quit()
|
||||
|
||||
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
|
||||
def pytest_runtest_makereport(item, call):
|
||||
"""
|
||||
Хук для получения результатов теста
|
||||
"""
|
||||
outcome = yield
|
||||
rep = outcome.get_result()
|
||||
setattr(item, "rep_" + rep.when, rep)
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def gen_data_fixture(auth_admin: APIClient, api_user_data, api_post_data):
|
||||
with allure.step("Generating data"):
|
||||
id = ''
|
||||
user = api_user_data[0]
|
||||
resp = auth_admin.create_user(user)
|
||||
assert resp.status_code == 201
|
||||
id = resp.json()['id']
|
||||
|
||||
post = api_post_data[0]
|
||||
post['userId'] = id
|
||||
auth_admin.create_post(post)
|
||||
yield
|
||||
|
||||
with allure.step("Deleting generated data"):
|
||||
posts = auth_admin.get_all_posts().json()
|
||||
users = auth_admin.get_all_users().json()
|
||||
|
||||
for post in posts:
|
||||
auth_admin.delete_post(post['id'])
|
||||
|
||||
for user in users:
|
||||
auth_admin.delete_user(user['id'])
|
||||
0
tests/ui/pages/__init__.py
Normal file
0
tests/ui/pages/__init__.py
Normal file
134
tests/ui/pages/admin_page.py
Normal file
134
tests/ui/pages/admin_page.py
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
import allure
|
||||
from selenium.webdriver.chrome.webdriver import WebDriver
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
from tests.ui.pages.base_page import BasePage
|
||||
|
||||
|
||||
class AdminPage(BasePage):
|
||||
# Локаторы
|
||||
|
||||
# Логин
|
||||
LOGIN_BLOCK = (By.XPATH, "//div[contains(@id, 'operations-user-post_login')]//button[contains(@class, 'opblock-summary-control')]")
|
||||
LOGIN_TRYITOUT_BTN = (By.XPATH, "//div[contains(@id, 'operations-user-post_login')]//button[contains(@class, 'try-out__btn')]")
|
||||
LOGIN_TEXTAREA = (By.XPATH, "//div[contains(@id, 'operations-user-post_login')]//textarea[contains(@class, 'body-param__text')]")
|
||||
LOGIN_EXECUTE_BTN = (By.XPATH, "//div[contains(@id, 'operations-user-post_login')]//button[contains(@class, 'execute')]")
|
||||
LOGIN_STATUS_CODE = (By.XPATH, "//div[contains(@id, 'operations-user-post_login')]//table[contains(@class, 'live-responses-table')]//tbody//td[contains(@class, 'response-col_status')]")
|
||||
|
||||
# Пользователь
|
||||
USER_BLOCK = (By.XPATH, "//div[contains(@id, 'operations-user-post_team_')]//button[contains(@class, 'opblock-summary-control')]")
|
||||
USER_TRYITOUT_BTN = (By.XPATH, "//div[contains(@id, 'operations-user-post_team_')]//button[contains(@class, 'try-out__btn')]")
|
||||
USER_TEXTAREA = (By.XPATH, "//div[contains(@id, 'operations-user-post_team_')]//textarea[contains(@class, 'body-param__text')]")
|
||||
USER_EXECUTE_BTN = (By.XPATH, "//div[contains(@id, 'operations-user-post_team_')]//button[contains(@class, 'execute')]")
|
||||
USER_RESPONSE = (By.XPATH, "//div[contains(@id, 'operations-user-post_team_')]//table[contains(@class, 'live-responses-table')]//tbody//td[contains(@class, 'response-col_description')]//code")
|
||||
USER_STATUS_CODE = (By.XPATH, "//div[contains(@id, 'operations-user-post_team_')]//table[contains(@class, 'live-responses-table')]//tbody//td[contains(@class, 'response-col_status')]")
|
||||
|
||||
# Данные для входа
|
||||
LOGIN_DATA = [Keys.BACKSPACE, Keys.ENTER, '\t"password": "Abc1205",', Keys.ENTER, '\t"username": "muts"', Keys.ENTER, '}']
|
||||
USER_RAW_DATA = """
|
||||
"avatar": "🔍",
|
||||
"description": "QA‑инженер с фокусом на автоматизированное тестирование и CI/CD.",
|
||||
"joinDate": "2023-10-01T20:00:00Z",
|
||||
"motto": "Тестирование — это поиск истины.",
|
||||
"name": "Андрей Васильев",
|
||||
"password": "TestPas1205",
|
||||
"projects": ["Web App Testing", "API Automation"],
|
||||
"role": "QA Engineer",
|
||||
"skills": ["Selenium", "JUnit", "Postman", "CI/CD", "TestRail"],
|
||||
"speciality": "Good user",
|
||||
"username": "andrey_user"
|
||||
}
|
||||
"""
|
||||
USER_DATA = [Keys.BACKSPACE, USER_RAW_DATA]
|
||||
|
||||
def __init__(self, driver: WebDriver):
|
||||
super().__init__(driver)
|
||||
|
||||
@allure.step('Открытие страницы администратора')
|
||||
def open_admin_page(self):
|
||||
self.open('http://localhost:8080/swagger/index.html')
|
||||
|
||||
@allure.step('Проверка наличия блока логина')
|
||||
def is_login_block_visible(self):
|
||||
return self.is_visible(self.LOGIN_BLOCK)
|
||||
|
||||
@allure.step('Проверка наличия кнопки "try it out"')
|
||||
def is_login_tryitout_btn_visible(self):
|
||||
return self.is_visible(self.LOGIN_TRYITOUT_BTN)
|
||||
|
||||
@allure.step('Проверка наличия поля ввода')
|
||||
def is_login_textarea_visible(self):
|
||||
return self.is_visible(self.LOGIN_TEXTAREA)
|
||||
|
||||
@allure.step('Проверка наличия кнопки выполнения запроса')
|
||||
def is_login_execute_btn_visible(self):
|
||||
return self.is_visible(self.LOGIN_EXECUTE_BTN)
|
||||
|
||||
@allure.step('Нажатие на блок логина')
|
||||
def click_login_block(self):
|
||||
self.click(self.LOGIN_BLOCK)
|
||||
|
||||
@allure.step('Нажатие на кнопку "try it out"')
|
||||
def click_login_tryitout_btn(self):
|
||||
self.click(self.LOGIN_TRYITOUT_BTN)
|
||||
|
||||
@allure.step('Ввод текста в поле логина')
|
||||
def enter_text_to_login_textarea(self, text: list):
|
||||
field = self.find_element(self.LOGIN_TEXTAREA)
|
||||
field.clear()
|
||||
|
||||
for event in text:
|
||||
field.send_keys(event)
|
||||
|
||||
@allure.step('Нажатие на кнопку выполнения запроса')
|
||||
def click_login_execute_btn(self):
|
||||
self.click(self.LOGIN_EXECUTE_BTN)
|
||||
|
||||
@allure.step('Получение статуса выполнения входа')
|
||||
def get_login_status(self):
|
||||
return self.get_text(self.LOGIN_STATUS_CODE)
|
||||
|
||||
@allure.step('Проверка наличия блока пользователя')
|
||||
def is_user_block_visible(self):
|
||||
return self.is_visible(self.USER_BLOCK)
|
||||
|
||||
@allure.step('Проверка наличия кнопки "try it out"')
|
||||
def is_user_tryitout_btn_visible(self):
|
||||
return self.is_visible(self.USER_TRYITOUT_BTN)
|
||||
|
||||
@allure.step('Проверка наличия поля ввода')
|
||||
def is_user_textarea_visible(self):
|
||||
return self.is_visible(self.USER_TEXTAREA)
|
||||
|
||||
@allure.step('Проверка наличия кнопки выполнения запроса')
|
||||
def is_user_execute_btn_visible(self):
|
||||
return self.is_visible(self.USER_EXECUTE_BTN)
|
||||
|
||||
@allure.step('Нажатие на блок пользователя')
|
||||
def click_user_block(self):
|
||||
self.click(self.USER_BLOCK)
|
||||
|
||||
@allure.step('Нажатие на кнопку "try it out"')
|
||||
def click_user_tryitout_btn(self):
|
||||
self.click(self.USER_TRYITOUT_BTN)
|
||||
|
||||
@allure.step('Ввод текста в поле добавления пользователя')
|
||||
def enter_text_to_user_textarea(self, text: list):
|
||||
field = self.find_element(self.USER_TEXTAREA)
|
||||
field.clear()
|
||||
|
||||
for event in text:
|
||||
field.send_keys(event)
|
||||
|
||||
@allure.step('Нажатие на кнопку выполнения запроса')
|
||||
def click_user_execute_btn(self):
|
||||
self.click(self.USER_EXECUTE_BTN)
|
||||
|
||||
@allure.step('Получение ответа на запрос создания пользователя')
|
||||
def get_user_response(self):
|
||||
elem = self.find_element(self.USER_RESPONSE)
|
||||
return elem.get_attribute('innerText')
|
||||
|
||||
@allure.step('Получение статуса создания пользователя')
|
||||
def get_user_status(self):
|
||||
return self.get_text(self.USER_STATUS_CODE)
|
||||
99
tests/ui/pages/base_page.py
Normal file
99
tests/ui/pages/base_page.py
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
from selenium.webdriver import ActionChains
|
||||
from selenium.webdriver.chrome.webdriver import WebDriver
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.common.exceptions import TimeoutException, NoSuchElementException
|
||||
import allure
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BasePage:
|
||||
def __init__(self, driver: WebDriver):
|
||||
self.driver = driver
|
||||
self.wait = WebDriverWait(driver, 10)
|
||||
self.logger = logger
|
||||
|
||||
@allure.step("Открыть URL: {url}")
|
||||
def open(self, url):
|
||||
self.driver.get(url)
|
||||
self.logger.info(f"Открыта страница: {url}")
|
||||
|
||||
@allure.step("Обновить страницу")
|
||||
def refresh(self):
|
||||
self.driver.refresh()
|
||||
self.logger.info("Страница обновлена")
|
||||
|
||||
@allure.step("Найти элемент: {locator}")
|
||||
def find_element(self, locator):
|
||||
try:
|
||||
element = self.wait.until(EC.visibility_of_element_located(locator))
|
||||
self.logger.debug(f"Элемент найден: {locator}")
|
||||
return element
|
||||
except TimeoutException:
|
||||
self.logger.error(f"Элемент не найден: {locator}")
|
||||
allure.attach(
|
||||
self.driver.get_screenshot_as_png(),
|
||||
name="element_not_found",
|
||||
attachment_type=allure.attachment_type.PNG
|
||||
)
|
||||
raise
|
||||
|
||||
@allure.step("Кликнуть на элемент: {locator}")
|
||||
def click(self, locator):
|
||||
element = self.find_element(locator)
|
||||
element.click()
|
||||
self.logger.info(f"Клик по элементу: {locator}")
|
||||
|
||||
@allure.step("Ввести текст '{text}' в элемент: {locator}")
|
||||
def type_text(self, locator, text):
|
||||
element = self.find_element(locator)
|
||||
element.clear()
|
||||
element.send_keys(text)
|
||||
self.logger.info(f"Введен текст '{text}' в элемент: {locator}")
|
||||
|
||||
@allure.step("Получить текст элемента: {locator}")
|
||||
def get_text(self, locator):
|
||||
element = self.find_element(locator)
|
||||
text = element.text
|
||||
self.logger.info(f"Получен текст '{text}' из элемента: {locator}")
|
||||
return text
|
||||
|
||||
@allure.step("Проверить, что элемент видим: {locator}")
|
||||
def is_visible(self, locator):
|
||||
try:
|
||||
element = self.find_element(locator)
|
||||
is_displayed = element.is_displayed()
|
||||
self.logger.info(f"Элемент {locator} видим: {is_displayed}")
|
||||
return is_displayed
|
||||
except (TimeoutException, NoSuchElementException):
|
||||
return False
|
||||
|
||||
@allure.step("Получить текущий URL")
|
||||
def get_current_url(self):
|
||||
url = self.driver.current_url
|
||||
self.logger.info(f"Текущий URL: {url}")
|
||||
return url
|
||||
|
||||
@allure.step("Сделать скриншот")
|
||||
def take_screenshot(self, name="screenshot"):
|
||||
screenshot = self.driver.get_screenshot_as_png()
|
||||
allure.attach(
|
||||
screenshot,
|
||||
name=name,
|
||||
attachment_type=allure.attachment_type.PNG
|
||||
)
|
||||
self.logger.info(f"Скриншот сохранен: {name}")
|
||||
|
||||
@allure.step("Ожидание загрузки элемента: {locator}")
|
||||
def wait_for_element(self, locator, timeout=10):
|
||||
wait = WebDriverWait(self.driver, timeout)
|
||||
element = wait.until(EC.visibility_of_element_located(locator))
|
||||
self.logger.info(f"Элемент загружен: {locator}")
|
||||
return element
|
||||
|
||||
@allure.step("Скролл до элемента")
|
||||
def scroll_to_element(self, locator):
|
||||
element = self.find_element(locator)
|
||||
self.driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", element)
|
||||
92
tests/ui/pages/home_page.py
Normal file
92
tests/ui/pages/home_page.py
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
import allure
|
||||
from selenium.webdriver.common.by import By
|
||||
from config.ui_config import UIConfig
|
||||
from tests.ui.pages.base_page import BasePage
|
||||
|
||||
|
||||
class HomePage(BasePage):
|
||||
# Локаторы
|
||||
LOGO = (By.CLASS_NAME, "logo-text")
|
||||
TEAM_TITLE = (By.XPATH, "//div[contains(@class, 'team-panel')]//h3")
|
||||
ARTICLE_TITLE = (By.XPATH, "//div[contains(@class, 'blog-panel')]//h3")
|
||||
TIME = (By.ID, "current-time")
|
||||
TEAM_SECTION = (By.CLASS_NAME, "team-carousel")
|
||||
ARTICLE_SECTION = (By.CLASS_NAME, "articles-list")
|
||||
TEAM_NOT_FOUND = (By.XPATH, "//div[contains(@class, 'team-carousel')]//div[contains(@class, 'empty-state')]/span[not(contains(@class, 'empty-icon'))]")
|
||||
ARTICLE_NOT_FOUND = (By.XPATH, "//div[contains(@class, 'articles-list')]//div[contains(@class, 'empty-state')]/span[not(contains(@class, 'empty-icon'))]")
|
||||
AUTHOR_CARD = (By.CLASS_NAME, "team-member-card")
|
||||
ARTICLE_CARD = (By.CLASS_NAME, "article-preview")
|
||||
TEAM_VIEW_ALL = (By.XPATH, "//div[contains(@class, 'team-panel')]//a[contains(@class, 'view-all')]")
|
||||
ARTICLE_VIEW_ALL = (By.XPATH, "//div[contains(@class, 'blog-panel')]//a[contains(@class, 'view-all')]")
|
||||
|
||||
def __init__(self, driver):
|
||||
super().__init__(driver)
|
||||
|
||||
@allure.step("Открытие домашней страницы")
|
||||
def open_home_page(self):
|
||||
self.open(UIConfig.UI_BASE_URL)
|
||||
|
||||
@allure.step("Проверка большого лого")
|
||||
def check_home_logo(self):
|
||||
text = self.get_text(self.LOGO)
|
||||
assert text == "Team"
|
||||
return text
|
||||
|
||||
@allure.step("Проверка заголовка списка команды")
|
||||
def check_home_team(self):
|
||||
text = self.get_text(self.TEAM_TITLE)
|
||||
assert text == "MEET THE TEAM"
|
||||
return text
|
||||
|
||||
@allure.step("Проверка заголовка списка постов")
|
||||
def check_home_posts(self):
|
||||
text = self.get_text(self.ARTICLE_TITLE)
|
||||
assert text == "LATEST ARTICLES"
|
||||
return text
|
||||
|
||||
@allure.step("Проверить наличие раздела 'Meet the Team'")
|
||||
def is_meet_the_team_section_displayed(self):
|
||||
return self.is_visible(self.TEAM_SECTION)
|
||||
|
||||
@allure.step("Проверить наличие раздела 'Latest Articles'")
|
||||
def is_latest_articles_section_displayed(self):
|
||||
return self.is_visible(self.ARTICLE_SECTION)
|
||||
|
||||
@allure.step("Проверить сообщение 'No team members found'")
|
||||
def check_no_team_members_message(self):
|
||||
message = self.get_text(self.TEAM_NOT_FOUND)
|
||||
assert "No team members found" in message, \
|
||||
f"Ожидалось сообщение 'No team members found', получено '{message}'"
|
||||
return message
|
||||
|
||||
@allure.step("Проверить сообщение 'No articles found'")
|
||||
def check_no_articles_message(self):
|
||||
message = self.get_text(self.ARTICLE_NOT_FOUND)
|
||||
assert "No articles found" in message, \
|
||||
f"Ожидалось сообщение 'No articles found', получено '{message}'"
|
||||
return message
|
||||
|
||||
@allure.step("Проверить наличие карточки автора")
|
||||
def is_member_card_displayed(self):
|
||||
return self.is_visible(self.AUTHOR_CARD)
|
||||
|
||||
@allure.step("Проверить наличие карточки статьи")
|
||||
def is_article_card_displayed(self):
|
||||
return self.is_visible(self.ARTICLE_CARD)
|
||||
|
||||
@allure.step("Проверить видимость кнопки VIEW ALL TEAM")
|
||||
def is_team_view_all_displayed(self):
|
||||
return self.is_visible(self.TEAM_VIEW_ALL)
|
||||
|
||||
@allure.step("Проверить видимость кнопки VIEW ALL TEAM")
|
||||
def is_article_view_all_displayed(self):
|
||||
return self.is_visible(self.ARTICLE_VIEW_ALL)
|
||||
|
||||
@allure.step("Проверить кликабельность кнопки VIEW ALL TEAM")
|
||||
def click_view_all_team_button(self):
|
||||
self.click(self.TEAM_VIEW_ALL)
|
||||
|
||||
@allure.step("Проверить кликабельность кнопки VIEW ALL TEAM")
|
||||
def click_view_all_article_button(self):
|
||||
self.click(self.ARTICLE_VIEW_ALL)
|
||||
|
||||
158
tests/ui/test_admin_page.py
Normal file
158
tests/ui/test_admin_page.py
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
|
||||
import json
|
||||
import time
|
||||
import allure
|
||||
import pytest
|
||||
from selenium.webdriver.chrome.webdriver import WebDriver
|
||||
|
||||
from config.ui_config import UIConfig
|
||||
from tests.api.utils.api_client import APIClient
|
||||
from tests.ui.pages.admin_page import AdminPage
|
||||
|
||||
|
||||
@allure.epic("Страница администратора")
|
||||
@allure.feature("Основной функционал")
|
||||
class TestAdminPage:
|
||||
@allure.story("Загрузка страницы")
|
||||
@allure.title("Проверка успешной загрузки страницы")
|
||||
@allure.severity(allure.severity_level.BLOCKER)
|
||||
@pytest.mark.smoke
|
||||
@pytest.mark.ui
|
||||
def test_page_load_succesfull(self, driver):
|
||||
admin_page = AdminPage(driver)
|
||||
|
||||
with allure.step('1. Открыть страницу'):
|
||||
admin_page.open_admin_page()
|
||||
admin_page.take_screenshot("admin_page")
|
||||
|
||||
@allure.story("Структура страницы")
|
||||
@allure.title("Проверка отображения элементов")
|
||||
@allure.severity(allure.severity_level.BLOCKER)
|
||||
@pytest.mark.smoke
|
||||
@pytest.mark.ui
|
||||
def test_page_elements_visiblity(self, driver):
|
||||
admin_page = AdminPage(driver)
|
||||
|
||||
with allure.step('1. Открыть страницу'):
|
||||
admin_page.open_admin_page()
|
||||
admin_page.take_screenshot("admin_page")
|
||||
|
||||
with allure.step('2. Проверка наличия кнопки блока логина'):
|
||||
assert admin_page.is_login_block_visible(), 'Кнопка блока логина не отобразилась'
|
||||
|
||||
with allure.step('3. Проверка невидимости кнопки "try it out"'):
|
||||
assert not admin_page.is_login_tryitout_btn_visible(), 'Кнопка не должна быть видима'
|
||||
|
||||
with allure.step('4. Проверка невидимости поля ввода'):
|
||||
assert not admin_page.is_login_textarea_visible(), 'Поле ввода не должно быть видимо'
|
||||
|
||||
with allure.step('5. Проверка невидимости кнопки выполнения запроса'):
|
||||
assert not admin_page.is_login_execute_btn_visible(), 'Кнопка выполнения запроса не должна быть видимой'
|
||||
|
||||
@allure.story("Функциональность")
|
||||
@allure.title("Проверка функциональности страницы")
|
||||
@allure.severity(allure.severity_level.BLOCKER)
|
||||
@pytest.mark.smoke
|
||||
@pytest.mark.ui
|
||||
def test_page_login_process(self, driver: WebDriver):
|
||||
admin_page = AdminPage(driver)
|
||||
|
||||
with allure.step('1. Открыть страницу'):
|
||||
admin_page.open_admin_page()
|
||||
admin_page.wait_for_element(admin_page.LOGIN_BLOCK)
|
||||
admin_page.scroll_to_element(admin_page.LOGIN_BLOCK)
|
||||
admin_page.take_screenshot("admin_page")
|
||||
|
||||
with allure.step('2. Нажать на блок логина'):
|
||||
admin_page.click_login_block()
|
||||
assert admin_page.is_login_tryitout_btn_visible(), 'Кнопка "try it out" должна быть видимой'
|
||||
|
||||
with allure.step('3. Нажать на кнопку "try it out"'):
|
||||
admin_page.click_login_tryitout_btn()
|
||||
assert admin_page.is_login_textarea_visible(), 'Поле ввода должно быть видимым'
|
||||
assert admin_page.is_login_execute_btn_visible(), 'Кнопка выполнения запроса должна быть видимой'
|
||||
admin_page.scroll_to_element(admin_page.LOGIN_TRYITOUT_BTN)
|
||||
admin_page.take_screenshot('admin_page_login_block')
|
||||
|
||||
with allure.step('4. Ввод данных для входа'):
|
||||
admin_page.scroll_to_element(admin_page.LOGIN_TEXTAREA)
|
||||
admin_page.take_screenshot("admin_page_login_area_unchanged")
|
||||
admin_page.enter_text_to_login_textarea(admin_page.LOGIN_DATA)
|
||||
time.sleep(0.5)
|
||||
admin_page.take_screenshot("admin_page_login_text_entered")
|
||||
|
||||
with allure.step('5. Выполнение запроса'):
|
||||
admin_page.click_login_execute_btn()
|
||||
time.sleep(2.0)
|
||||
admin_page.scroll_to_element(admin_page.LOGIN_STATUS_CODE)
|
||||
admin_page.take_screenshot("admin_page_login_request_executed")
|
||||
|
||||
with allure.step('6. Проверка статуса выполнения запроса'):
|
||||
admin_page.scroll_to_element(admin_page.LOGIN_STATUS_CODE)
|
||||
assert int(admin_page.get_login_status()) == 200
|
||||
|
||||
@allure.story("Добавление пользователя")
|
||||
@allure.title("Проверка функции добавления пользователя")
|
||||
@allure.severity(allure.severity_level.BLOCKER)
|
||||
@pytest.mark.smoke
|
||||
@pytest.mark.ui
|
||||
def test_page_user_adding(self, driver: WebDriver, auth_admin: APIClient):
|
||||
admin_page = AdminPage(driver)
|
||||
user_id = ''
|
||||
|
||||
with allure.step('1. Открыть страницу'):
|
||||
admin_page.open_admin_page()
|
||||
admin_page.wait_for_element(admin_page.USER_BLOCK)
|
||||
admin_page.scroll_to_element(admin_page.USER_BLOCK)
|
||||
admin_page.take_screenshot("admin_page")
|
||||
|
||||
with allure.step("2. Авторизоваться"):
|
||||
admin_page.click_login_block()
|
||||
admin_page.click_login_tryitout_btn()
|
||||
admin_page.enter_text_to_login_textarea(admin_page.LOGIN_DATA)
|
||||
time.sleep(0.5)
|
||||
admin_page.click_login_execute_btn()
|
||||
time.sleep(2.0)
|
||||
admin_page.scroll_to_element(admin_page.LOGIN_STATUS_CODE)
|
||||
admin_page.take_screenshot("admin_page_login_request_executed")
|
||||
|
||||
with allure.step('3. Нажать на блок пользователя'):
|
||||
admin_page.click_user_block()
|
||||
assert admin_page.is_user_tryitout_btn_visible(), 'Кнопка "try it out" должна быть видимой'
|
||||
|
||||
with allure.step('4. Нажать на кнопку "try it out"'):
|
||||
admin_page.click_user_tryitout_btn()
|
||||
assert admin_page.is_user_textarea_visible(), 'Поле ввода должно быть видимым'
|
||||
assert admin_page.is_user_execute_btn_visible(), 'Кнопка выполнения запроса должна быть видимой'
|
||||
admin_page.scroll_to_element(admin_page.USER_TRYITOUT_BTN)
|
||||
admin_page.take_screenshot('admin_page_user_block')
|
||||
|
||||
with allure.step('5. Ввод данных для регистрации пользователя'):
|
||||
admin_page.scroll_to_element(admin_page.USER_TEXTAREA)
|
||||
admin_page.take_screenshot("admin_page_user_area_unchanged")
|
||||
admin_page.enter_text_to_user_textarea(admin_page.USER_DATA)
|
||||
time.sleep(0.5)
|
||||
admin_page.take_screenshot("admin_page_user_text_entered")
|
||||
|
||||
with allure.step('6. Выполнение запроса'):
|
||||
admin_page.click_user_execute_btn()
|
||||
time.sleep(2.0)
|
||||
admin_page.scroll_to_element(admin_page.USER_STATUS_CODE)
|
||||
admin_page.take_screenshot("admin_page_user_request_executed")
|
||||
|
||||
with allure.step('7. Проверка статуса выполнения запроса'):
|
||||
admin_page.scroll_to_element(admin_page.LOGIN_STATUS_CODE)
|
||||
assert int(admin_page.get_login_status()) == 200
|
||||
|
||||
with allure.step('8. Сохраняем id пользователя для удаления'):
|
||||
content = admin_page.get_user_response()
|
||||
user_id = json.loads(content)['id']
|
||||
|
||||
with allure.step('9. Проверка, что пользователь добавлен на сайт'):
|
||||
admin_page.open(UIConfig.get_url('team'))
|
||||
time.sleep(2)
|
||||
admin_page.take_screenshot('team_page_user')
|
||||
|
||||
with allure.step('10. Удаляем пользователя через API'):
|
||||
auth_admin.delete_user(user_id)
|
||||
|
||||
224
tests/ui/test_home_page.py
Normal file
224
tests/ui/test_home_page.py
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
import pytest
|
||||
import allure
|
||||
from selenium.webdriver.chrome.webdriver import WebDriver
|
||||
from config.ui_config import UIConfig
|
||||
import time
|
||||
|
||||
from tests.ui.pages.home_page import HomePage
|
||||
|
||||
|
||||
@allure.epic("Домашняя страница")
|
||||
@allure.feature("Основной функционал")
|
||||
class TestTeamPage:
|
||||
|
||||
@allure.story("Загрузка страницы")
|
||||
@allure.title("Проверка успешной загрузки страницы")
|
||||
@allure.severity(allure.severity_level.BLOCKER)
|
||||
@pytest.mark.smoke
|
||||
@pytest.mark.ui
|
||||
def test_page_load_successfully(self, driver):
|
||||
"""
|
||||
Тест проверяет успешную загрузку страницы Team
|
||||
"""
|
||||
home_page = HomePage(driver)
|
||||
|
||||
with allure.step("1. Открыть страницу"):
|
||||
home_page.open_home_page()
|
||||
home_page.take_screenshot("home_page_loaded")
|
||||
|
||||
with allure.step("2. Проверить заголовок окна браузера"):
|
||||
page_title = driver.title
|
||||
allure.attach(page_title, name="page_title", attachment_type=allure.attachment_type.TEXT)
|
||||
assert page_title, "Заголовок страницы пустой"
|
||||
|
||||
@allure.story("Контент страницы")
|
||||
@allure.title("Проверка текстового содержания страницы")
|
||||
@allure.severity(allure.severity_level.CRITICAL)
|
||||
@pytest.mark.regression
|
||||
def test_page_content_validation(self, driver):
|
||||
"""
|
||||
Тест проверяет корректность текстового содержания страницы
|
||||
"""
|
||||
home_page = HomePage(driver)
|
||||
|
||||
with allure.step("1. Открыть страницу"):
|
||||
home_page.open_home_page()
|
||||
|
||||
with allure.step("2. Проверить заголовок"):
|
||||
title = home_page.get_text(home_page.LOGO)
|
||||
assert title == "Team", f"Неверный заголовок: {title}"
|
||||
|
||||
|
||||
with allure.step("4. Проверить сообщения о пустом состоянии"):
|
||||
team_message = home_page.check_no_team_members_message()
|
||||
articles_message = home_page.check_no_articles_message()
|
||||
|
||||
allure.attach(
|
||||
f"Сообщение о команде: {team_message}\nСообщение о статьях: {articles_message}",
|
||||
name="empty_state_messages",
|
||||
attachment_type=allure.attachment_type.TEXT
|
||||
)
|
||||
|
||||
with allure.step("5. Сделать скриншот всей страницы"):
|
||||
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
|
||||
time.sleep(1)
|
||||
home_page.take_screenshot("full_page_content")
|
||||
|
||||
@allure.story("Структура страницы")
|
||||
@allure.title("Проверка структуры и порядка элементов")
|
||||
@allure.severity(allure.severity_level.NORMAL)
|
||||
@pytest.mark.ui
|
||||
def test_page_structure(self, driver):
|
||||
"""
|
||||
Тест проверяет правильность структуры расположения элементов
|
||||
"""
|
||||
home_page = HomePage(driver)
|
||||
|
||||
with allure.step("1. Открыть страницу Team"):
|
||||
home_page.open_home_page()
|
||||
|
||||
with allure.step("2. Проверить наличие всех разделов"):
|
||||
assert home_page.is_meet_the_team_section_displayed(), \
|
||||
"Раздел 'MEET THE TEAM' не отображается"
|
||||
assert home_page.is_latest_articles_section_displayed(), \
|
||||
"Раздел 'LATEST ARTICLES' не отображается"
|
||||
|
||||
with allure.step("3. Проверить кнопку VIEW ALL team"):
|
||||
button = home_page.is_team_view_all_displayed()
|
||||
assert button, "Кнопка не отобразилась"
|
||||
|
||||
with allure.step("4. Проверить кнопку VIEW ALL article"):
|
||||
button = home_page.is_article_view_all_displayed()
|
||||
assert button, "Кнопка не отобразилась"
|
||||
|
||||
@allure.story("Функциональность")
|
||||
@allure.title("Проверка кликабельности элементов")
|
||||
@allure.severity(allure.severity_level.NORMAL)
|
||||
@pytest.mark.regression
|
||||
def test_elements_interactivity(self, driver):
|
||||
"""
|
||||
Тест проверяет кликабельность интерактивных элементов
|
||||
"""
|
||||
home_page = HomePage(driver)
|
||||
|
||||
with allure.step("1. Открыть страницу Team"):
|
||||
home_page.open_home_page()
|
||||
|
||||
with allure.step("2. Проверить кликабельность кнопки VIEW ALL team"):
|
||||
button_team = home_page.find_element(home_page.TEAM_VIEW_ALL)
|
||||
assert button_team.is_enabled(), "Кнопка VIEW ALL не активна"
|
||||
|
||||
# Проверяем, что это ссылка
|
||||
tag_name = button_team.tag_name
|
||||
assert tag_name.lower() in ['a', 'button'], \
|
||||
f"Элемент не является ссылкой или кнопкой (тег: {tag_name})"
|
||||
|
||||
with allure.step("3. Проверить кликабельность кнопки VIEW ALL article"):
|
||||
button_article = home_page.find_element(home_page.ARTICLE_VIEW_ALL)
|
||||
assert button_article.is_enabled(), "Кнопка VIEW ALL не активна"
|
||||
|
||||
# Проверяем, что это ссылка
|
||||
tag_name = button_article.tag_name
|
||||
assert tag_name.lower() in ['a', 'button'], \
|
||||
f"Элемент не является ссылкой или кнопкой (тег: {tag_name})"
|
||||
|
||||
|
||||
with allure.step("4. Навести курсор на кнопку VIEW ALL team"):
|
||||
from selenium.webdriver.common.action_chains import ActionChains
|
||||
actions = ActionChains(driver)
|
||||
actions.move_to_element(button_team).perform()
|
||||
time.sleep(0.5)
|
||||
|
||||
# Проверяем изменение стиля (опционально)
|
||||
home_page.take_screenshot("team_view_all_button_hover")
|
||||
|
||||
with allure.step("4. Навести курсор на кнопку VIEW ALL article"):
|
||||
from selenium.webdriver.common.action_chains import ActionChains
|
||||
actions = ActionChains(driver)
|
||||
actions.move_to_element(button_article).perform()
|
||||
time.sleep(0.5)
|
||||
|
||||
# Проверяем изменение стиля (опционально)
|
||||
home_page.take_screenshot("article_view_all_button_hover")
|
||||
|
||||
|
||||
@allure.story("Навигация")
|
||||
@allure.title("Проверка поведения кнопки VIEW ALL")
|
||||
@allure.severity(allure.severity_level.CRITICAL)
|
||||
@pytest.mark.smoke
|
||||
def test_view_all_button_functionality(self, driver: WebDriver):
|
||||
"""
|
||||
Тест проверяет функциональность кнопки VIEW ALL
|
||||
"""
|
||||
home_page = HomePage(driver)
|
||||
|
||||
with allure.step("1. Открыть страницу Team"):
|
||||
home_page.open_home_page()
|
||||
initial_url = driver.current_url
|
||||
allure.attach(initial_url, name="initial_url", attachment_type=allure.attachment_type.TEXT)
|
||||
|
||||
with allure.step("2. Нажать кнопку VIEW ALL team"):
|
||||
home_page.click_view_all_team_button()
|
||||
time.sleep(2) # Ждем загрузки
|
||||
|
||||
new_url = driver.current_url
|
||||
allure.attach(new_url, name="new_url", attachment_type=allure.attachment_type.TEXT)
|
||||
|
||||
with allure.step("3. Проверить изменение URL"):
|
||||
# Проверяем, что URL изменился (или остался тем же, если это anchor link)
|
||||
assert new_url == UIConfig.get_url("team"), "Совершен переход на неверную страницу"
|
||||
|
||||
with allure.step("4. Возвращаемся на главную"):
|
||||
driver.back()
|
||||
|
||||
with allure.step("2. Нажать кнопку VIEW ALL article"):
|
||||
home_page.click_view_all_article_button()
|
||||
time.sleep(2) # Ждем загрузки
|
||||
|
||||
new_url = driver.current_url
|
||||
allure.attach(new_url, name="new_url", attachment_type=allure.attachment_type.TEXT)
|
||||
|
||||
with allure.step("3. Проверить изменение URL"):
|
||||
# Проверяем, что URL изменился (или остался тем же, если это anchor link)
|
||||
assert new_url == UIConfig.get_url("blog"), "Совершен переход на неверную страницу"
|
||||
|
||||
@allure.story("Контент страницы")
|
||||
@allure.title("Проверка появления карточек")
|
||||
@allure.severity(allure.severity_level.CRITICAL)
|
||||
@pytest.mark.regression
|
||||
def test_cards_visiblity(self, driver, gen_data_fixture):
|
||||
"""
|
||||
Тест проверяет появление предложенных карточек
|
||||
"""
|
||||
home_page = HomePage(driver)
|
||||
|
||||
with allure.step("1. Открыть страницу"):
|
||||
home_page.open_home_page()
|
||||
|
||||
with allure.step("2. Проверка существования карточки автора"):
|
||||
card = home_page.is_member_card_displayed()
|
||||
assert card, "Карточка пользователя не отобразилась"
|
||||
|
||||
with allure.step("3. Проверка реакции карточки на наведение"):
|
||||
from selenium.webdriver.common.action_chains import ActionChains
|
||||
member_card = home_page.find_element(home_page.AUTHOR_CARD)
|
||||
actions = ActionChains(driver)
|
||||
actions.move_to_element(member_card).perform()
|
||||
time.sleep(0.5)
|
||||
|
||||
home_page.take_screenshot("Member_card_hower_reaction")
|
||||
|
||||
with allure.step("4. Проверка существования карточки статьи"):
|
||||
card = home_page.is_article_card_displayed()
|
||||
assert card, "Карточка статьи не отобразилась"
|
||||
|
||||
with allure.step("5. Проверка реакции карточки на наведение"):
|
||||
from selenium.webdriver.common.action_chains import ActionChains
|
||||
member_card = home_page.find_element(home_page.ARTICLE_CARD)
|
||||
actions = ActionChains(driver)
|
||||
actions.move_to_element(member_card).perform()
|
||||
time.sleep(0.5)
|
||||
|
||||
home_page.take_screenshot("Member_card_hower_reaction")
|
||||
|
||||
|
||||
0
tests/ui/utils/__init__.py
Normal file
0
tests/ui/utils/__init__.py
Normal file
0
tests/ui/utils/wait.py
Normal file
0
tests/ui/utils/wait.py
Normal file
Loading…
Add table
Add a link
Reference in a new issue