From ba62a4eb856980d296ac7b151b0a2728f5ac89f8 Mon Sep 17 00:00:00 2001 From: k0te1ch Date: Sat, 15 Aug 2026 17:36:05 +0300 Subject: [PATCH] refactor(bot): drop legacy wordpress module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit app/bot/utils/wordpress.py hasn't been imported by anything since WordPress publishing moved to app/publishers/WordPress — only its own tests referenced it, and the README already flagged it as legacy. It carried a pickle.load of a cookie jar, a swallowed exception and three open TODOs. Also drops WP_COOKIE_FILENAME / WP_COOKIE_PATH from the bot config and .env.example: the publisher reads its own WP_COOKIE_PATH from shared config, so the bot-side pair was dead with the module. --- .env.example | 1 - app/bot/config.py | 3 - app/bot/utils/wordpress.py | 211 ------------------ .../wordpress/class_methods/test_enter.py | 3 - .../wordpress/class_methods/test_exit.py | 30 --- tests/unit/utils/wordpress/conftest.py | 34 --- .../wordpress/cookies/test_dump_cookies.py | 70 ------ .../wordpress/cookies/test_load_cookies.py | 42 ---- .../methods/test_get_last_post_id.py | 14 -- .../wordpress/methods/test_upload_post.py | 59 ----- .../util/session/test_check_session.py | 21 -- .../wordpress/util/session/test_close.py | 7 - .../wordpress/util/session/test_login.py | 116 ---------- .../util/session/test_make_session.py | 21 -- 14 files changed, 632 deletions(-) delete mode 100644 app/bot/utils/wordpress.py delete mode 100644 tests/unit/utils/wordpress/class_methods/test_enter.py delete mode 100644 tests/unit/utils/wordpress/class_methods/test_exit.py delete mode 100644 tests/unit/utils/wordpress/conftest.py delete mode 100644 tests/unit/utils/wordpress/cookies/test_dump_cookies.py delete mode 100644 tests/unit/utils/wordpress/cookies/test_load_cookies.py delete mode 100644 tests/unit/utils/wordpress/methods/test_get_last_post_id.py delete mode 100644 tests/unit/utils/wordpress/methods/test_upload_post.py delete mode 100644 tests/unit/utils/wordpress/util/session/test_check_session.py delete mode 100644 tests/unit/utils/wordpress/util/session/test_close.py delete mode 100644 tests/unit/utils/wordpress/util/session/test_login.py delete mode 100644 tests/unit/utils/wordpress/util/session/test_make_session.py diff --git a/.env.example b/.env.example index e251987..1bd5c31 100644 --- a/.env.example +++ b/.env.example @@ -129,7 +129,6 @@ COVER_PS_NAME = "pscover.jpg" PODCAST = "podcast.mp3" FILES_PATH = "files" LOGS_PATH = "logs" -WP_COOKIE_FILENAME = "cookie.pkl" # KAFKA SETTINGS KAFKA_SERVER = "kafka:9092" diff --git a/app/bot/config.py b/app/bot/config.py index 6e6957a..3177492 100644 --- a/app/bot/config.py +++ b/app/bot/config.py @@ -96,7 +96,6 @@ class Settings(BaseSettings): COVER_RZ_NAME: str | None = None COVER_PS_NAME: str | None = None PODCAST: str | None = None - WP_COOKIE_FILENAME: str | None = None FILES_PATH: str = "files" LOGS_PATH: str = "logs" LOGS_ZIP_NAME: str = "logs.zip" @@ -231,7 +230,6 @@ def parse_developer(cls, v: Any) -> int | None: COVER_RZ_NAME = settings.COVER_RZ_NAME COVER_PS_NAME = settings.COVER_PS_NAME PODCAST = settings.PODCAST -WP_COOKIE_FILENAME = settings.WP_COOKIE_FILENAME LOGS_ZIP_NAME = settings.LOGS_ZIP_NAME FILES_PATH: Path = PROJECT_PATH / settings.FILES_PATH @@ -240,7 +238,6 @@ def parse_developer(cls, v: Any) -> int | None: PODCAST_PATH = FILES_PATH / PODCAST if PODCAST else FILES_PATH / "podcast.mp3" COVER_RZ_PATH = FILES_PATH / COVER_RZ_NAME if COVER_RZ_NAME else FILES_PATH / "cover.jpg" COVER_PS_PATH = FILES_PATH / COVER_PS_NAME if COVER_PS_NAME else FILES_PATH / "pscover.jpg" -WP_COOKIE_PATH = FILES_PATH / WP_COOKIE_FILENAME if WP_COOKIE_FILENAME else FILES_PATH / "cookie.pkl" KEYBOARDS_PATH = SRC_PATH / KEYBOARDS_DIR if KEYBOARDS_DIR else SRC_PATH / "keyboards" diff --git a/app/bot/utils/wordpress.py b/app/bot/utils/wordpress.py deleted file mode 100644 index f2d8fd3..0000000 --- a/app/bot/utils/wordpress.py +++ /dev/null @@ -1,211 +0,0 @@ -import os -import pickle -import re -import warnings -from datetime import datetime - -import feedparser -import requests -from fake_useragent import UserAgent -from loguru import logger -from lxml import etree -from requests import Response - -from config import TIMEZONE, WP_COOKIE_PATH, WP_LOGIN, WP_PASSWORD, WP_URL - -# TODO make this async -# TODO: обернуть всё в определённый -# TODO: Проблема с куками и сессией - - -class WordPress: - """ - A class for interacting with a WordPress site via the API. - - Attributes: - _session (requests.Session): A session for sending HTTP requests. - _filename (str): The path to the file for saving cookies. - _userAgent (fake_useragent.UserAgent): A fake random user agent. - - Methods: - __init__: Initialize the class and create a session. - __enter__: Enter method for context management. - __exit__: Exit method for context management. - _dump_cookies: Save cookies to a file. - _load_cookies: Load cookies from a file. - _login: Authenticate on a WordPress site. - _check_session: Check the session status. - _make_session: Create a session with cookies in mind. - close: Close the session. - upload_post: Upload a new post to the site. - get_last_post_id: Get the ID of the last uploaded post. - """ - - _instance = None - _session: requests.Session = requests.Session() - _filename: str = WP_COOKIE_PATH - _userAgent: UserAgent = UserAgent().random - - def __new__(cls, *args, **kwargs): - if not cls._instance: - cls._instance = super().__new__(cls) - return cls._instance - - def __init__(self): - if not hasattr(self, "_initialized"): - self._initialized = True # Флаг, чтобы инициализация выполнялась только раз - self._session = None - self._make_session() - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - self.close() - - def _dump_cookies(self) -> bool: - if not self._filename: - raise ValueError("Имя файла не может быть пустым") - - try: - with open(self._filename, "wb") as f: - pickle.dump(self._session.cookies, f) - return True - except Exception as e: - print(f"Ошибка сохранения куков: {e}") - return False - - def _load_cookies(self) -> bool: - if os.path.exists(self._filename) and os.path.getsize(self._filename) > 0: - with open(self._filename, "rb") as f: - self._session.cookies.update(pickle.load(f)) - return True - return False - - def _login(self) -> bool: - url = f"{WP_URL}/wp-login.php" - self._session.cookies["wordpress_test_cookie"] = "WP Cookie check" - self._session.cookies["wp_lang"] = "ru_RU" - form = { - "log": WP_LOGIN, - "pwd": WP_PASSWORD, - "rememberme": "forever", - "wp-submit": "Войти", - "redirect_to": f"{WP_URL}/wp-admin/", - "testcookie": 1, - } - s = self._session.post(url, data=form) - - if ( - s.status_code == 200 - and f'document.location.href="{WP_URL.replace("https", "http")}/wp-login.php' in s.text - ): - cookie_matches = re.findall(r'document\.cookie="(.*?)";', s.text) - for match in cookie_matches: - cookie_parts = match.split(";") - for part in cookie_parts: - if "=" in part: - name, value = part.strip().split("=", 1) - self._session.cookies[name.strip()] = value.strip() - - s = self._session.post(url, data=form) - if s.status_code == 200 and f'document.location.href="{WP_URL.replace("https", "http")}/wp-admin' in s.text: - return self._dump_cookies() - return False - - def _check_session(self) -> bool: - return ( - f'document.location.href="{WP_URL.replace("https", "http")}/wp-login.php?redirect_to=' - not in self._session.get(f"{WP_URL}/wp-admin/").text - ) - - def _make_session(self) -> requests.Session: - self._session.headers = {"User-Agent": self._userAgent} - if not (self._load_cookies() and self._check_session()): - self._login() - - return self._session - - def close(self): - self._session.close() - - def upload_post(self, info: dict) -> str: - logger.debug("Starting post upload process") - post = self._session.get(f"{WP_URL}/wp-admin/post-new.php?post_type=podcast").content - - logger.debug("Retrieved post content from WordPress") - - #! TODO check if exist - - html_dom = etree.HTML(post, etree.HTMLParser()) - podcastID = info["number"] - name = info["title"] - summary = info["comment"] - chapters = "" - for time, chapterName in info["chapters"]: - chapters += f"[skipto time={time}]{time}[/skipto] — {chapterName}\n" - - time = datetime.now(TIMEZONE) - - timeStr = f"{time.day} {('января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря')[time.month - 1]} {time.year}" # TODO Locale settings! - - form = { # TODO refactor this (name.replace...) - "post_title": f"Разговорный жанр — {podcastID}", - "content": f"""{name.replace(podcastID + ". ", "")} - -Описание: -{summary} - -Таймлайн: -{chapters} - -Всё это вы услышите в {podcastID}-м эпизоде подкаста «Разговорный жанр». -[podlove-template template="subscriptions"] -Дата записи: {timeStr}""", - "post_name": f"Разговорный жанр — {podcastID}", - "post_category[]": "3", - "newcategory": "Название новой рубрики", - "newcategory_parent": "-1", - "_podlove_meta[number]": podcastID, - "_podlove_meta[title]": f"Разговорный жанр — {podcastID}", - "_podlove_meta[summary]": summary, - "_podlove_meta[type]": "full", - "episode_contributor[0][1][id]": "1", - "episode_contributor[0][1][comment]": "", - "episode_contributor[0][3][id]": "3", - "episode_contributor[0][3][comment]": "", - "_podlove_meta[recording_date]": time.strftime("%Y-%m-%d"), - "_podlove_meta[slug]": info["slug"], - "_podlove_meta[chapters]": "\n".join(" ".join(x) for x in info["chapters"]), - "_podlove_meta[duration]": info["duration"], - "_podlove_meta[episode_assets][1]": "on", - "trackback_url": "", - "metakeyselect": "big_post", - "metakeyinput": "", - "metavalue": "1", - "comment_status": "open", - "ping_status": "open", - "post_author_override": "361", - "tax_input[shows]": "0", - "referredby": f"{WP_URL}/wp-admin/profile.php", - "_wp_original_http_referer": f"{WP_URL}/wp-admin/profile.php", - "tax_input[post_tag]": ",".join(info["tags"]), - "newtag[post_tag]": "", - "_podlove_meta[subtitle]": "", - "_thumbnail_id": "6038", - } - form_element = html_dom.find('.//form[@name="post"]') - for field in form_element.xpath('.//input[@type="hidden"]'): - field = field.attrib - if field["name"] not in form: - form[field["name"]] = field["value"] - - logger.debug("Submitting post data to WordPress") - response: Response = self._session.post(f"{WP_URL}/wp-admin/post.php", data=form) - logger.debug(f"Uploaded post with response code: {response.status_code}") # TODO - - @staticmethod - def get_last_post_ID() -> str: # Deprecated - warnings.warn("get_last_post_ID is deprecated", DeprecationWarning, stacklevel=2) - feed = feedparser.parse(f"{WP_URL}/feed/podcast/") - return feed["entries"][0]["itunes_episode"] diff --git a/tests/unit/utils/wordpress/class_methods/test_enter.py b/tests/unit/utils/wordpress/class_methods/test_enter.py deleted file mode 100644 index 96184a9..0000000 --- a/tests/unit/utils/wordpress/class_methods/test_enter.py +++ /dev/null @@ -1,3 +0,0 @@ -def test_enter_method(wordpress): - with wordpress as entered_wp: - assert entered_wp is wordpress diff --git a/tests/unit/utils/wordpress/class_methods/test_exit.py b/tests/unit/utils/wordpress/class_methods/test_exit.py deleted file mode 100644 index e002a41..0000000 --- a/tests/unit/utils/wordpress/class_methods/test_exit.py +++ /dev/null @@ -1,30 +0,0 @@ -from unittest.mock import patch - -import pytest - -from utils.wordpress import WordPress - - -@patch.object(WordPress, "close") -def test_exit_method_calls_close(mock_close, wordpress): - with wordpress: - pass - # Проверяем, что метод close был вызван при выходе из контекста - mock_close.assert_called_once() - - -@patch.object(WordPress, "close") -def test_exit_method_without_exception(mock_close, wordpress): - with wordpress: - pass - # Проверяем, что close вызывается при отсутствии исключения - mock_close.assert_called_once() - - -@patch.object(WordPress, "close") -def test_exit_method_with_exception(mock_close, wordpress): - with pytest.raises(ValueError): - with wordpress: - raise ValueError("Test exception") - # Проверяем, что close вызывается, даже если произошло исключение - mock_close.assert_called_once() diff --git a/tests/unit/utils/wordpress/conftest.py b/tests/unit/utils/wordpress/conftest.py deleted file mode 100644 index f5b46cf..0000000 --- a/tests/unit/utils/wordpress/conftest.py +++ /dev/null @@ -1,34 +0,0 @@ -from collections import UserDict -from unittest.mock import MagicMock, patch - -import pytest - -from utils.wordpress import WordPress - - -class TrackingDict(UserDict): - def update(self, *args, **kwargs): - super().update(*args, **kwargs) - - -@pytest.fixture(autouse=True) -def mock_session(): - with patch("utils.wordpress.requests.Session", new_callable=MagicMock) as MockSession: - session_instance = MockSession.return_value - session_instance.post = MagicMock() - session_instance.get = MagicMock() - - cookies = TrackingDict() - cookies.update = MagicMock(wraps=cookies.update) - session_instance.cookies = cookies - session_instance.headers = {} - yield session_instance - - -@pytest.fixture -def wordpress(mock_session): - with patch.object(WordPress, "__init__", lambda self: None): - WordPress._instance = None - wordpress_instance = WordPress() - wordpress_instance._session = mock_session - yield wordpress_instance diff --git a/tests/unit/utils/wordpress/cookies/test_dump_cookies.py b/tests/unit/utils/wordpress/cookies/test_dump_cookies.py deleted file mode 100644 index 5c10630..0000000 --- a/tests/unit/utils/wordpress/cookies/test_dump_cookies.py +++ /dev/null @@ -1,70 +0,0 @@ -from unittest.mock import patch - -import pytest - - -@patch("utils.wordpress.pickle.dump") -@patch("utils.wordpress.open", create=True) -def test_dump_cookies_success(mock_open, mock_pickle, wordpress, mock_session): - """Тест на успешное сохранение куков""" - wordpress._filename = "test_cookies.pkl" - mock_session.cookies = {"test_cookie": "value"} - - mock_open.return_value.__enter__.return_value = mock_open - - result = wordpress._dump_cookies() - - assert result, "Метод _dump_cookies должен возвращать True при успешном сохранении" - mock_pickle.assert_called_once_with(mock_session.cookies, mock_open) - - -@patch("utils.wordpress.pickle.dump", side_effect=Exception("Ошибка сохранения")) -@patch("utils.wordpress.open", create=True) -def test_dump_cookies_fail(mock_open, mock_pickle, wordpress, mock_session): - """Тест на ошибку при попытке сохранить куки""" - - wordpress._filename = "test_cookies.pkl" - - mock_session.cookies = {"test_cookie": "value"} - - mock_open.return_value.__enter__.return_value = mock_open - - # Проверка на случай возникновения ошибки - result = wordpress._dump_cookies() - - assert not result, "Метод _dump_cookies должен возвращать False при ошибке сохранения" - mock_pickle.assert_called_once() - - -@patch("utils.wordpress.pickle.dump") -@patch("utils.wordpress.open", create=True) -def test_dump_cookies_no_cookies(mock_open, mock_pickle, wordpress, mock_session): - """Тест на случай, когда в сессии нет куков для сохранения""" - - wordpress._filename = "test_cookies.pkl" - - mock_session.cookies = {} - - mock_open.return_value.__enter__.return_value = mock_open - - result = wordpress._dump_cookies() - - assert result, "Метод _dump_cookies должен возвращать True даже при отсутствии куков" - mock_pickle.assert_called_once_with(mock_session.cookies, mock_open) - - -@patch("utils.wordpress.pickle.dump") -@patch("utils.wordpress.open", create=True) -def test_dump_cookies_empty_filename(mock_open, mock_pickle, wordpress, mock_session): - """Тест на случай отсутствия имени файла для сохранения""" - - wordpress._filename = "" # Пустое имя файла - - mock_session.cookies = {"test_cookie": "value"} - - mock_open.return_value.__enter__.return_value = mock_open - - # Проверка выполнения метода при пустом имени файла - with pytest.raises(ValueError, match="Имя файла не может быть пустым"): - wordpress._dump_cookies() - mock_pickle.assert_not_called() diff --git a/tests/unit/utils/wordpress/cookies/test_load_cookies.py b/tests/unit/utils/wordpress/cookies/test_load_cookies.py deleted file mode 100644 index a40ad27..0000000 --- a/tests/unit/utils/wordpress/cookies/test_load_cookies.py +++ /dev/null @@ -1,42 +0,0 @@ -from unittest.mock import mock_open, patch - - -@patch("os.path.exists", return_value=True) -@patch("os.path.getsize", return_value=10) -@patch("builtins.open", new_callable=mock_open) -@patch("pickle.load", return_value={"cookie_name": "cookie_value"}) -def test_load_cookies_file_exists_and_has_content( - mock_pickle_load, mock_open, mock_getsize, mock_exists, wordpress, mock_session -): - # Выполняем метод _load_cookies - result = wordpress._load_cookies() - - # Проверяем, что файл открылся и cookies обновлены - mock_open.assert_called_once_with(wordpress._filename, "rb") - mock_pickle_load.assert_called_once() - mock_session.cookies.update.assert_called_once_with({"cookie_name": "cookie_value"}) - assert result is True # Метод должен вернуть True - - -@patch("os.path.exists") -@patch("os.path.getsize") -def test_load_cookies_file_does_not_exist(mock_getsize, mock_exists, wordpress): - mock_exists.return_value = False # Файл не существует - mock_getsize.return_value = 0 # Размер не имеет значения, т.к. файл отсутствует - - result = wordpress._load_cookies() - - # Проверяем, что метод вернул False, так как файла нет - assert result is False - - -@patch("os.path.exists") -@patch("os.path.getsize") -def test_load_cookies_file_is_empty(mock_getsize, mock_exists, wordpress): - mock_exists.return_value = True # Файл существует - mock_getsize.return_value = 0 # Файл пустой - - result = wordpress._load_cookies() - - # Проверяем, что метод вернул False, так как файл пустой - assert result is False diff --git a/tests/unit/utils/wordpress/methods/test_get_last_post_id.py b/tests/unit/utils/wordpress/methods/test_get_last_post_id.py deleted file mode 100644 index 518573a..0000000 --- a/tests/unit/utils/wordpress/methods/test_get_last_post_id.py +++ /dev/null @@ -1,14 +0,0 @@ -from unittest.mock import patch - -import pytest - - -@patch("utils.wordpress.feedparser.parse") -def test_get_last_post_id(mock_feedparser, wordpress): - mock_feedparser.return_value = {"entries": [{"itunes_episode": "123"}]} - - with pytest.warns(DeprecationWarning, match="get_last_post_ID is deprecated"): - last_post_id = wordpress.get_last_post_ID() - - assert last_post_id == "123" - mock_feedparser.assert_called_once() diff --git a/tests/unit/utils/wordpress/methods/test_upload_post.py b/tests/unit/utils/wordpress/methods/test_upload_post.py deleted file mode 100644 index 481dc94..0000000 --- a/tests/unit/utils/wordpress/methods/test_upload_post.py +++ /dev/null @@ -1,59 +0,0 @@ -def test_upload_post(mock_session, caplog, wordpress): - info = { - "number": "1", - "title": "Test Title", - "comment": "Test Comment", - "chapters": [("00:00", "Intro")], - "slug": "test-slug", - "duration": "00:30", - "tags": ["test", "post"], - } - - # Настройка mock-ответов для запросов - mock_session.get.return_value.content = b"
" - mock_session.post.return_value.status_code = 200 - - # Выполнение метода upload_post - with caplog.at_level("DEBUG"): - wordpress.upload_post(info) - - # Проверка наличия определенного сообщения в логах - assert any("Starting post upload process" in record.message for record in caplog.records), ( - "Сообщение 'Starting post upload process' должно быть залогировано" - ) - - # Проверка вызова post запроса - mock_session.post.assert_called() - - -def test_upload_post_hidden_fields(mock_session, wordpress): - # Предопределяем HTML-структуру с формой, содержащей скрытые поля - html_content = """ -
- - -
- """ - - # Замокированный ответ от `self._session.get` - mock_session.get.return_value.content = html_content.encode("utf-8") - - # Тестируемые данные для загрузки - info = { - "number": "123", - "title": "Test Title", - "comment": "Test Summary", - "chapters": [("00:00", "Intro")], - "slug": "test-slug", - "duration": "10:00", - "tags": ["tag1", "tag2"], - } - - # Выполняем функцию `upload_post` - wordpress.upload_post(info) - - # Проверяем, что скрытые поля добавлены - assert "hidden_field_1" in mock_session.post.call_args[1]["data"] - assert mock_session.post.call_args[1]["data"]["hidden_field_1"] == "hidden_value_1" - assert "hidden_field_2" in mock_session.post.call_args[1]["data"] - assert mock_session.post.call_args[1]["data"]["hidden_field_2"] == "hidden_value_2" diff --git a/tests/unit/utils/wordpress/util/session/test_check_session.py b/tests/unit/utils/wordpress/util/session/test_check_session.py deleted file mode 100644 index 0a30c20..0000000 --- a/tests/unit/utils/wordpress/util/session/test_check_session.py +++ /dev/null @@ -1,21 +0,0 @@ -from config import WP_URL - - -def test_check_session_active(mock_session, wordpress): - """Тест для активной сессии.""" - # Настраиваем mock для возвращения текста, указывающего на активную сессию - mock_session.get.return_value.text = "wp-admin" - - # Проверяем, что метод _check_session() возвращает True при активной сессии - assert wordpress._check_session(), "Сессия должна быть активной, но тест этого не подтверждает." - - -def test_check_session_inactive(mock_session, wordpress): - """Тест для неактивной сессии.""" - # Настраиваем mock для возвращения текста, указывающего на перенаправление на страницу входа - mock_session.get.return_value.text = ( - f'document.location.href="{WP_URL.replace("https", "http")}/wp-login.php?redirect_to=' - ) - - # Проверяем, что метод _check_session() возвращает False при неактивной сессии - assert not wordpress._check_session(), "Сессия должна быть неактивной, но тест этого не подтверждает." diff --git a/tests/unit/utils/wordpress/util/session/test_close.py b/tests/unit/utils/wordpress/util/session/test_close.py deleted file mode 100644 index ca52259..0000000 --- a/tests/unit/utils/wordpress/util/session/test_close.py +++ /dev/null @@ -1,7 +0,0 @@ -def test_close_session(mock_session, wordpress): - """Тестирует метод close для корректного завершения сессии.""" - # Вызываем метод close() и проверяем, что он корректно закрывает сессию - wordpress.close() - - # Проверяем, что метод close у mock_session был вызван ровно один раз - mock_session.close.assert_called_once(), "Метод close() не был вызван один раз на сессии." diff --git a/tests/unit/utils/wordpress/util/session/test_login.py b/tests/unit/utils/wordpress/util/session/test_login.py deleted file mode 100644 index b163cc8..0000000 --- a/tests/unit/utils/wordpress/util/session/test_login.py +++ /dev/null @@ -1,116 +0,0 @@ -from unittest.mock import Mock, patch - -from config import WP_URL - - -@patch("utils.wordpress.WordPress._dump_cookies", return_value=True) -def test_login_success(mock_dump_cookies, wordpress, mock_session): - """Тест на успешный логин, когда метод возвращает True""" - - # Настраиваем mock для первого запроса - mock_response_first = Mock() - mock_response_first.status_code = 200 - mock_response_first.text = ( - f'document.cookie="wordpress_logged_in=some_value; path=/";' - f'document.location.href="{WP_URL.replace("https", "http")}/wp-login.php"' - ) - - # Настраиваем mock для второго запроса - mock_response_second = Mock() - mock_response_second.status_code = 200 - mock_response_second.text = f'document.location.href="{WP_URL.replace("https", "http")}/wp-admin"' - - # Указываем возвращаемые значения для двух вызовов `post` - mock_session.post.side_effect = [mock_response_first, mock_response_second] - - assert wordpress._login(), "Логин должен быть успешным, но метод вернул False" - mock_dump_cookies.assert_called_once() - - -@patch("utils.wordpress.WordPress._dump_cookies", return_value=True) -def test_login_failed_status_code(mock_dump_cookies, wordpress, mock_session): - """Тест на неудачный логин из-за неверного статус-кода""" - mock_response = Mock() - mock_response.status_code = 403 # Например, доступ запрещен - mock_session.post.return_value = mock_response - - result = wordpress._login() - assert not result, "Метод должен возвращать False при неуспешном статусе входа" - mock_dump_cookies.assert_not_called() - - -@patch("utils.wordpress.WordPress._dump_cookies", return_value=False) -def test_login_failed_redirect(mock_dump_cookies, wordpress, mock_session): - """Тест на неудачный логин из-за отсутствия перенаправления на страницу входа""" - mock_response = Mock() - mock_response.status_code = 200 - mock_response.text = "Some other text without redirect" - mock_session.post.return_value = mock_response - - assert not wordpress._login(), "Метод должен возвращать False при отсутствии перенаправления на логин." - mock_dump_cookies.assert_not_called() - - -@patch("utils.wordpress.WordPress._dump_cookies", return_value=True) -def test_login_cookie_setting(mock_dump_cookies, wordpress, mock_session): - """Тест на установку куки при успешном логине""" - - # Настраиваем mock для первого запроса - mock_response_first = Mock() - mock_response_first.status_code = 200 - mock_response_first.text = ( - f'document.cookie="wordpress_logged_in=some_value; path=/";' - f'document.location.href="{WP_URL.replace("https", "http")}/wp-login.php"' - ) - - # Настраиваем mock для второго запроса - mock_response_second = Mock() - mock_response_second.status_code = 200 - mock_response_second.text = f'document.location.href="{WP_URL.replace("https", "http")}/wp-admin"' - - # Указываем side_effect для обработки двух вызовов `post` - mock_session.post.side_effect = [mock_response_first, mock_response_second] - - wordpress._login() - - # Проверяем, что куки 'wordpress_logged_in' добавлен - assert "wordpress_logged_in" in mock_session.cookies, "Cookie wordpress_logged_in не установлен." - assert mock_session.cookies["wordpress_logged_in"] == "some_value", ( - "Неверное значение для куки wordpress_logged_in." - ) - - # Проверка вызова _dump_cookies - mock_dump_cookies.assert_called_once() - - -@patch("utils.wordpress.WordPress._dump_cookies", return_value=True) -def test_login_multiple_cookie_handling(mock_dump_cookies, wordpress, mock_session): - """Тест на корректное управление несколькими куками при успешном логине""" - - # Настройка mock для первого ответа с двумя куками - mock_response_first = Mock() - mock_response_first.status_code = 200 - mock_response_first.text = ( - 'document.cookie="wordpress_logged_in=some_value; path=/";' - 'document.cookie="another_cookie=another_value; path=/";' - f'document.location.href="{WP_URL.replace("https", "http")}/wp-login.php"' - ) - - # Настройка mock для второго ответа с перенаправлением на wp-admin - mock_response_second = Mock() - mock_response_second.status_code = 200 - mock_response_second.text = f'document.location.href="{WP_URL.replace("https", "http")}/wp-admin"' - - # Указываем последовательность ответов для вызовов post - mock_session.post.side_effect = [mock_response_first, mock_response_second] - - wordpress._login() - - # Проверка наличия и корректности значений куков - assert "wordpress_logged_in" in mock_session.cookies, "Cookie wordpress_logged_in не установлен." - assert mock_session.cookies["wordpress_logged_in"] == "some_value", "Неверное значение для wordpress_logged_in." - assert "another_cookie" in mock_session.cookies, "Cookie another_cookie не установлен." - assert mock_session.cookies["another_cookie"] == "another_value", "Неверное значение для another_cookie." - - # Проверка вызова _dump_cookies - mock_dump_cookies.assert_called_once() diff --git a/tests/unit/utils/wordpress/util/session/test_make_session.py b/tests/unit/utils/wordpress/util/session/test_make_session.py deleted file mode 100644 index f6d9e14..0000000 --- a/tests/unit/utils/wordpress/util/session/test_make_session.py +++ /dev/null @@ -1,21 +0,0 @@ -from unittest.mock import patch - -from utils.wordpress import WordPress - - -@patch("utils.wordpress.WordPress._load_cookies", return_value=True) -@patch("utils.wordpress.WordPress._check_session", return_value=True) -@patch("utils.wordpress.WordPress._login") -def test_make_session_with_valid_session(mock_login, mock_check_session, mock_load_cookies, wordpress): - wordpress._make_session() - - mock_login.assert_not_called() - - -@patch.object(WordPress, "_login", autospec=True) -@patch.object(WordPress, "_load_cookies", side_effect=lambda: False) -@patch.object(WordPress, "_check_session", side_effect=lambda: False) -def test_make_session_with_invalid_session(mock_check_session, mock_load_cookies, mock_login, wordpress): - wordpress._make_session() - - mock_login.assert_called_once()