import asyncio import os import tempfile from datetime import datetime import pytest from database.models import MessageContentLink, PostContent, TelegramPost from database.repositories.post_repository import PostRepository class TestPostRepositoryIntegration: """Интеграционные тесты для PostRepository с реальной БД.""" async def _setup_test_database(self, post_repository): """Вспомогательная функция для настройки тестовой БД.""" # Сначала создаем таблицу our_users для тестов await post_repository._execute_query(""" CREATE TABLE IF NOT EXISTS our_users ( user_id INTEGER NOT NULL PRIMARY KEY, first_name TEXT, full_name TEXT, username TEXT, is_bot BOOLEAN DEFAULT 0, language_code TEXT, has_stickers BOOLEAN DEFAULT 0 NOT NULL, emoji TEXT, date_added INTEGER NOT NULL, date_changed INTEGER NOT NULL, voice_bot_welcome_received BOOLEAN DEFAULT 0 ) """) # Добавляем тестовых пользователей await post_repository._execute_query( "INSERT OR REPLACE INTO our_users (user_id, first_name, full_name, date_added, date_changed) VALUES (?, ?, ?, ?, ?)", ( 67890, "Test", "Test User", int(datetime.now().timestamp()), int(datetime.now().timestamp()), ), ) await post_repository._execute_query( "INSERT OR REPLACE INTO our_users (user_id, first_name, full_name, date_added, date_changed) VALUES (?, ?, ?, ?, ?)", ( 11111, "Test2", "Test User 2", int(datetime.now().timestamp()), int(datetime.now().timestamp()), ), ) # Теперь создаем таблицы для постов await post_repository.create_tables() @pytest.fixture def temp_db_path(self): """Фикстура для временного файла БД.""" with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as tmp_file: db_path = tmp_file.name yield db_path # Очищаем временный файл после тестов try: os.unlink(db_path) except OSError: pass @pytest.fixture def post_repository(self, temp_db_path): """Фикстура для PostRepository с реальной БД.""" return PostRepository(temp_db_path) @pytest.fixture def sample_post(self): """Фикстура для тестового поста.""" return TelegramPost( message_id=12345, text="Тестовый пост для интеграционных тестов", author_id=67890, helper_text_message_id=None, created_at=int(datetime.now().timestamp()), ) @pytest.fixture def sample_post_2(self): """Фикстура для второго тестового поста.""" return TelegramPost( message_id=12346, text="Второй тестовый пост", author_id=67890, helper_text_message_id=None, created_at=int(datetime.now().timestamp()), ) @pytest.fixture def sample_post_with_helper(self): """Фикстура для тестового поста с helper сообщением.""" return TelegramPost( message_id=12347, text="Пост с helper сообщением", author_id=67890, helper_text_message_id=None, # Будет установлен позже created_at=int(datetime.now().timestamp()), ) @pytest.mark.asyncio async def test_create_tables_integration(self, post_repository): """Интеграционный тест создания таблиц.""" # Настраиваем тестовую БД await self._setup_test_database(post_repository) # Проверяем, что таблицы созданы (попробуем вставить тестовые данные) test_post = TelegramPost( message_id=99999, text="Тест создания таблиц", author_id=67890, # Используем существующего пользователя created_at=int(datetime.now().timestamp()), ) # Если таблицы созданы, то insert должен пройти успешно await post_repository.add_post(test_post) # Проверяем, что пост действительно добавлен author_id = await post_repository.get_author_id_by_message_id(99999) assert author_id == 67890 @pytest.mark.asyncio async def test_add_post_integration(self, post_repository, sample_post): """Интеграционный тест добавления поста.""" # Настраиваем тестовую БД await self._setup_test_database(post_repository) # Добавляем пост await post_repository.add_post(sample_post) # Проверяем, что пост добавлен author_id = await post_repository.get_author_id_by_message_id( sample_post.message_id ) assert author_id == sample_post.author_id @pytest.mark.asyncio async def test_add_post_without_date_integration(self, post_repository): """Интеграционный тест добавления поста без даты.""" # Настраиваем тестовую БД await self._setup_test_database(post_repository) post_without_date = TelegramPost( message_id=12348, text="Пост без даты", author_id=67890, helper_text_message_id=None, created_at=None, ) # Добавляем пост await post_repository.add_post(post_without_date) # Проверяем, что дата была установлена автоматически assert post_without_date.created_at is not None assert isinstance(post_without_date.created_at, int) assert post_without_date.created_at > 0 # Проверяем, что пост добавлен author_id = await post_repository.get_author_id_by_message_id( post_without_date.message_id ) assert author_id == post_without_date.author_id @pytest.mark.asyncio async def test_update_helper_message_integration( self, post_repository, sample_post ): """Интеграционный тест обновления helper сообщения.""" # Настраиваем тестовую БД await self._setup_test_database(post_repository) # Добавляем пост await post_repository.add_post(sample_post) # Обновляем helper сообщение helper_message_id = 88888 await post_repository.update_helper_message( sample_post.message_id, helper_message_id ) # Проверяем, что helper сообщение обновлено # Для этого нужно получить пост и проверить helper_text_message_id # Но у нас нет метода для получения поста по ID, поэтому проверяем косвенно # через get_author_id_by_helper_message_id author_id = await post_repository.get_author_id_by_helper_message_id( helper_message_id ) assert author_id == sample_post.author_id @pytest.mark.asyncio async def test_add_post_content_integration(self, post_repository, sample_post): """Интеграционный тест добавления контента поста.""" # Настраиваем тестовую БД await self._setup_test_database(post_repository) # Добавляем пост await post_repository.add_post(sample_post) # Добавляем контент message_id = 11111 content_name = "/path/to/test/photo.jpg" content_type = "photo" # Сначала нужно добавить сообщение с этим message_id в post_from_telegram_suggest # или использовать существующий message_id content_post = TelegramPost( message_id=message_id, text="Сообщение с контентом", author_id=11111, # Используем существующего пользователя created_at=int(datetime.now().timestamp()), ) await post_repository.add_post(content_post) result = await post_repository.add_post_content( sample_post.message_id, message_id, content_name, content_type ) # Проверяем, что контент добавлен успешно assert result is True # Проверяем, что контент действительно добавлен post_content = await post_repository.get_post_content_by_helper_id( sample_post.message_id ) # Поскольку у нас нет helper_message_id, контент не будет найден # Это нормальное поведение для данного теста assert isinstance(post_content, list) @pytest.mark.asyncio async def test_add_post_content_with_helper_message_integration( self, post_repository, sample_post_with_helper ): """Интеграционный тест добавления контента поста с helper сообщением.""" # Настраиваем тестовую БД await self._setup_test_database(post_repository) # Добавляем пост await post_repository.add_post(sample_post_with_helper) # Создаем helper сообщение helper_message_id = 99999 helper_post = TelegramPost( message_id=helper_message_id, text="Helper сообщение", author_id=67890, created_at=int(datetime.now().timestamp()), ) await post_repository.add_post(helper_post) # Обновляем пост, чтобы он ссылался на helper сообщение await post_repository.update_helper_message( sample_post_with_helper.message_id, helper_message_id ) # Добавляем контент message_id = 22222 content_name = "/path/to/test/video.mp4" content_type = "video" # Сначала нужно добавить сообщение с этим message_id в post_from_telegram_suggest content_post = TelegramPost( message_id=message_id, text="Сообщение с видео контентом", author_id=11111, # Используем существующего пользователя created_at=int(datetime.now().timestamp()), ) await post_repository.add_post(content_post) result = await post_repository.add_post_content( sample_post_with_helper.message_id, message_id, content_name, content_type ) # Проверяем, что контент добавлен успешно assert result is True # Проверяем, что контент действительно добавлен post_content = await post_repository.get_post_content_by_helper_id( helper_message_id ) assert len(post_content) == 1 assert post_content[0][0] == content_name assert post_content[0][1] == content_type @pytest.mark.asyncio async def test_get_post_text_by_helper_id_integration( self, post_repository, sample_post_with_helper ): """Интеграционный тест получения текста поста по helper ID.""" # Настраиваем тестовую БД await self._setup_test_database(post_repository) # Добавляем пост await post_repository.add_post(sample_post_with_helper) # Создаем helper сообщение helper_message_id = 99999 helper_post = TelegramPost( message_id=helper_message_id, text="Helper сообщение", author_id=67890, created_at=int(datetime.now().timestamp()), ) await post_repository.add_post(helper_post) # Обновляем пост, чтобы он ссылался на helper сообщение await post_repository.update_helper_message( sample_post_with_helper.message_id, helper_message_id ) # Получаем текст поста post_text = await post_repository.get_post_text_by_helper_id(helper_message_id) # Проверяем результат assert post_text == sample_post_with_helper.text @pytest.mark.asyncio async def test_get_post_text_by_helper_id_not_found_integration( self, post_repository ): """Интеграционный тест получения текста поста по несуществующему helper ID.""" # Настраиваем тестовую БД await self._setup_test_database(post_repository) # Пытаемся получить текст поста по несуществующему helper ID post_text = await post_repository.get_post_text_by_helper_id(99999) # Проверяем, что результат None assert post_text is None @pytest.mark.asyncio async def test_get_post_ids_by_helper_id_integration( self, post_repository, sample_post_with_helper ): """Интеграционный тест получения ID сообщений по helper ID.""" # Настраиваем тестовую БД await self._setup_test_database(post_repository) # Добавляем пост await post_repository.add_post(sample_post_with_helper) # Создаем helper сообщение helper_message_id = 99999 helper_post = TelegramPost( message_id=helper_message_id, text="Helper сообщение", author_id=67890, created_at=int(datetime.now().timestamp()), ) await post_repository.add_post(helper_post) # Обновляем пост, чтобы он ссылался на helper сообщение await post_repository.update_helper_message( sample_post_with_helper.message_id, helper_message_id ) # Добавляем несколько сообщений с контентом message_ids = [33333, 44444, 55555] content_names = [ "/path/to/photo1.jpg", "/path/to/photo2.jpg", "/path/to/video.mp4", ] content_types = ["photo", "photo", "video"] for i, (msg_id, content_name, content_type) in enumerate( zip(message_ids, content_names, content_types) ): # Сначала нужно добавить сообщение с этим message_id в post_from_telegram_suggest content_post = TelegramPost( message_id=msg_id, text=f"Сообщение с контентом {i+1}", author_id=11111, # Используем существующего пользователя created_at=int(datetime.now().timestamp()), ) await post_repository.add_post(content_post) result = await post_repository.add_post_content( sample_post_with_helper.message_id, msg_id, content_name, content_type ) assert result is True # Получаем ID сообщений post_ids = await post_repository.get_post_ids_by_helper_id(helper_message_id) # Проверяем результат assert len(post_ids) == 3 for msg_id in message_ids: assert msg_id in post_ids @pytest.mark.asyncio async def test_get_author_id_by_message_id_integration( self, post_repository, sample_post ): """Интеграционный тест получения ID автора по message ID.""" # Настраиваем тестовую БД await self._setup_test_database(post_repository) # Добавляем пост await post_repository.add_post(sample_post) # Получаем ID автора author_id = await post_repository.get_author_id_by_message_id( sample_post.message_id ) # Проверяем результат assert author_id == sample_post.author_id @pytest.mark.asyncio async def test_get_author_id_by_message_id_not_found_integration( self, post_repository ): """Интеграционный тест получения ID автора по несуществующему message ID.""" # Настраиваем тестовую БД await self._setup_test_database(post_repository) # Пытаемся получить ID автора по несуществующему message ID author_id = await post_repository.get_author_id_by_message_id(99999) # Проверяем, что результат None assert author_id is None @pytest.mark.asyncio async def test_get_author_id_by_helper_message_id_integration( self, post_repository, sample_post_with_helper ): """Интеграционный тест получения ID автора по helper message ID.""" # Настраиваем тестовую БД await self._setup_test_database(post_repository) # Добавляем пост await post_repository.add_post(sample_post_with_helper) # Создаем helper сообщение helper_message_id = 99999 helper_post = TelegramPost( message_id=helper_message_id, text="Helper сообщение", author_id=67890, created_at=int(datetime.now().timestamp()), ) await post_repository.add_post(helper_post) # Обновляем пост, чтобы он ссылался на helper сообщение await post_repository.update_helper_message( sample_post_with_helper.message_id, helper_message_id ) # Получаем ID автора author_id = await post_repository.get_author_id_by_helper_message_id( helper_message_id ) # Проверяем результат assert author_id == sample_post_with_helper.author_id @pytest.mark.asyncio async def test_get_author_id_by_helper_message_id_not_found_integration( self, post_repository ): """Интеграционный тест получения ID автора по несуществующему helper message ID.""" # Настраиваем тестовую БД await self._setup_test_database(post_repository) # Пытаемся получить ID автора по несуществующему helper message ID author_id = await post_repository.get_author_id_by_helper_message_id(99999) # Проверяем, что результат None assert author_id is None @pytest.mark.asyncio async def test_multiple_posts_integration( self, post_repository, sample_post, sample_post_2 ): """Интеграционный тест работы с несколькими постами.""" # Настраиваем тестовую БД await self._setup_test_database(post_repository) # Добавляем несколько постов await post_repository.add_post(sample_post) await post_repository.add_post(sample_post_2) # Проверяем, что оба поста добавлены author_id_1 = await post_repository.get_author_id_by_message_id( sample_post.message_id ) author_id_2 = await post_repository.get_author_id_by_message_id( sample_post_2.message_id ) assert author_id_1 == sample_post.author_id assert author_id_2 == sample_post_2.author_id # Проверяем, что посты имеют разные ID assert sample_post.message_id != sample_post_2.message_id assert sample_post.text != sample_post_2.text @pytest.mark.asyncio async def test_post_content_relationships_integration( self, post_repository, sample_post_with_helper ): """Интеграционный тест связей между постами и контентом.""" # Настраиваем тестовую БД await self._setup_test_database(post_repository) # Добавляем пост await post_repository.add_post(sample_post_with_helper) # Создаем helper сообщение helper_message_id = 99999 helper_post = TelegramPost( message_id=helper_message_id, text="Helper сообщение", author_id=67890, created_at=int(datetime.now().timestamp()), ) await post_repository.add_post(helper_post) # Обновляем пост, чтобы он ссылался на helper сообщение await post_repository.update_helper_message( sample_post_with_helper.message_id, helper_message_id ) # Добавляем контент разных типов content_data = [ (11111, "/path/to/photo1.jpg", "photo"), (22222, "/path/to/video1.mp4", "video"), (33333, "/path/to/audio1.mp3", "audio"), (44444, "/path/to/photo2.jpg", "photo"), ] for message_id, content_name, content_type in content_data: # Сначала нужно добавить сообщение с этим message_id в post_from_telegram_suggest content_post = TelegramPost( message_id=message_id, text=f"Сообщение с контентом {content_type}", author_id=11111, # Используем существующего пользователя created_at=int(datetime.now().timestamp()), ) await post_repository.add_post(content_post) result = await post_repository.add_post_content( sample_post_with_helper.message_id, message_id, content_name, content_type, ) assert result is True # Проверяем, что весь контент добавлен post_content = await post_repository.get_post_content_by_helper_id( helper_message_id ) assert len(post_content) == 4 # Проверяем, что ID сообщений получены правильно post_ids = await post_repository.get_post_ids_by_helper_id(helper_message_id) assert len(post_ids) == 4 # Проверяем, что все ожидаемые ID присутствуют expected_message_ids = [11111, 22222, 33333, 44444] for expected_id in expected_message_ids: assert expected_id in post_ids @pytest.mark.asyncio async def test_update_status_by_message_id_integration( self, post_repository, sample_post ): """Интеграционный тест обновления статуса одиночного поста.""" await self._setup_test_database(post_repository) await post_repository.add_post(sample_post) await post_repository.update_status_by_message_id( sample_post.message_id, "approved" ) rows = await post_repository._execute_query_with_result( "SELECT status FROM post_from_telegram_suggest WHERE message_id = ?", (sample_post.message_id,), ) assert len(rows) == 1 assert rows[0][0] == "approved" @pytest.mark.asyncio async def test_update_status_for_media_group_by_helper_id_integration( self, post_repository, sample_post_with_helper ): """Интеграционный тест обновления статуса медиагруппы по helper_message_id.""" await self._setup_test_database(post_repository) await post_repository.add_post(sample_post_with_helper) helper_message_id = 99999 helper_post = TelegramPost( message_id=helper_message_id, text="^", author_id=67890, helper_text_message_id=sample_post_with_helper.message_id, created_at=int(datetime.now().timestamp()), status="suggest", ) await post_repository.add_post(helper_post) await post_repository.update_helper_message( sample_post_with_helper.message_id, helper_message_id ) await post_repository.update_status_for_media_group_by_helper_id( helper_message_id, "declined" ) rows = await post_repository._execute_query_with_result( "SELECT status FROM post_from_telegram_suggest " "WHERE message_id = ? OR helper_text_message_id = ?", (helper_message_id, helper_message_id), ) assert len(rows) == 2 for row in rows: assert row[0] == "declined"