Исходный код pages.base_page

"""Базовый класс страницы для работы с Playwright.

Содержит общие методы для взаимодействия со страницей и API.
"""
import time
import json
from typing import Dict, Any
from playwright.sync_api import Page, Response, APIRequestContext, expect
from data.environment import host
from tools.logger import get_logger

logger = get_logger("BASE_PAGE")


[документация] class BasePage: """Базовый класс для работы со страницами через Playwright. Атрибуты: page (Page): Экземпляр страницы Playwright. """
[документация] def __init__(self, page: Page): """Инициализирует базовую страницу. Args: page (Page): Экземпляр страницы Playwright. """ self.page = page
# Действия:
[документация] def current_url(self) -> str: """Возвращает текущий URL страницы. Returns: str: Текущий URL страницы. """ return self.page.url
[документация] def open(self, uri) -> Response | None: """Открывает указанный URI в браузере. Args: uri (str): URI для открытия (без базового URL). Returns: Response | None: Ответ сервера или None в случае ошибки. """ return self.page.goto(f"{host.get_base_url()}{uri}", wait_until='domcontentloaded')
[документация] def page_reload(self) -> None: """Перезагружает текущую страницу.""" self.page.reload()
[документация] def wait_for_timeout(self, timeout: int) -> None: """Ожидает указанное количество миллисекунд. Args: timeout (int): Время ожидания в миллисекундах. """ self.page.wait_for_timeout(timeout)
[документация] def get_api_request_context(self) -> APIRequestContext: """Возвращает контекст API-запросов. Returns: APIRequestContext: Контекст для выполнения API-запросов. """ return self.page.context.request
[документация] def send_get_api_request(self, uri: str) -> Response: """Отправляет GET-запрос к API. Args: uri (str): URI API-эндпоинта (без базового URL). Returns: Response: Ответ сервера. """ api_request_context = self.get_api_request_context() token = host.get_access_token() # Проверяем что токен получен if not token: logger.error("Failed to get access token: token is None or empty") # Возвращаем заглушечный response или бросаем исключение # В Playwright можно создать mock response если нужно return None headers = {"Accept": "application/json", "Authorization": f"Bearer {token}"} full_url = f"{host.get_request_url()}{uri}" logger.debug("Sending GET request to: %s", full_url) response = api_request_context.get(full_url, headers=headers) # Логируем статус ответа logger.debug("GET response status: %s", response.status) return response
[документация] def send_post_api_request(self, uri: str, payload: Dict) -> Response: """Отправляет POST-запрос к API.""" api_request_context = self.get_api_request_context() token = host.get_access_token() if not token: logger.error("Failed to get access token: token is None or empty") return None headers = { "Accept": "application/json", "Content-Type": "application/json", "Authorization": f"Bearer {token}" } full_url = f"{host.get_request_url()}{uri}" logger.debug("Sending POST request to: %s", full_url) # Сериализуем payload в JSON json_data = json.dumps(payload) # Проверяем что сериализация прошла успешно if json_data is None: logger.error("Failed to serialize payload to JSON: result is None") return None if not isinstance(json_data, str): logger.error("Failed to serialize payload to JSON: expected string got %s", type(json_data)) return None response = api_request_context.post( full_url, headers=headers, data=json_data # Передаем сериализованный JSON как data ) logger.debug("POST response status: %s", response.status) return response
[документация] def get_response_body(self, response: Response) -> dict | list | None: """Извлекает тело ответа в format JSON. Args: response (Response): Ответ сервера. Returns: dict | list | None: Распарсенное тело ответа или None в случае ошибки. """ start_time = time.time() # Проверяем что response не None if response is None: logger.error("Response object is None") processing_time = time.time() - start_time logger.debug("Response processing time1: %.3f seconds", processing_time) return None # Проверяем статус ответа if response.status >= 400: logger.error("API request failed with status %s", response.status) processing_time = time.time() - start_time logger.debug("Response processing time2: %.3f seconds", processing_time) return None # Пытаемся получить JSON json_result = response.json() # Проверяем что результат не None if json_result is None: logger.error("JSON parsing returned None") processing_time = time.time() - start_time logger.debug("Response processing time3: %.3f seconds", processing_time) return None # Принимаем как словари, так и списки if not isinstance(json_result, (dict, list)): logger.error("Expected dict or list but got %s", type(json_result)) processing_time = time.time() - start_time logger.debug("Response processing time4: %.3f seconds", processing_time) return None processing_time = time.time() - start_time logger.debug("Response processing time5: %.3f seconds", processing_time) return json_result
# Проверки:
[документация] def check_URL(self, uri: str, msg: str) -> None: """Проверяет, что текущий URL соответствует ожидаемому. Args: uri (str): Ожидаемый URI (без базового URL). msg (str): Сообщение об ошибке при несоответствии. Raises: AssertionError: Если URL не соответствует ожидаемому. """ expect(self.page).to_have_url( # pylint: disable=expression-not-assigned f"{host.get_base_url()}{uri}", timeout=60000 ), msg
[документация] def check_equals(self, actual: Any, expected: Any, msg: str) -> None: """Проверяет равенство фактического и ожидаемого значений. Args: actual (Any): Фактическое значение. expected (Any): Ожидаемое значение. msg (str): Сообщение об ошибке при несоответствии. Raises: AssertionError: Если значения не равны. """ assert actual == expected, msg
[документация] def check_lists_equals(self, actual: list, expected: list, msg: str) -> None: """Рекурсивно проверяет равенство двух списков. Args: actual (list): Фактический список. expected (list): Ожидаемый список. msg (str): Сообщение об ошибке при несоответствии. Raises: AssertionError: Если списки не равны. """ def compare_lists(list1: list, list2: list) -> bool: """Вспомогательная функция для рекурсивного сравнения списков. Args: list1 (list): Первый список для сравнения. list2 (list): Второй список для сравнения. Returns: bool: True если списки идентичны, иначе False. """ if len(list1) != len(list2): return False for item1, item2 in zip(list1, list2): if isinstance(item1, list) and isinstance(item2, list): if not compare_lists(item1, item2): return False elif item1 != item2: return False return True assert compare_lists(actual, expected), msg