import re import pytest from unittest.mock import AsyncMock, MagicMock from db.repository import Repository from db.models import Post, SourceWebsite, SourceChannel from services.admin_bot import AdminBotService def test_start_command_regex(): pattern = r"(?i)^(/start(@\w+)?|/srart(@\w+)?|/strt(@\w+)?|/starrt(@\w+)?|/menu(@\w+)?|شروع|منو|منوی اصلی|🏠 منوی اصلی)(\s.*)?$" valid_inputs = [ "/start", "/START", "/start@copykar_2026_bot", "/start ", "/srart", "/srart@copykar_2026_bot", "/strt", "/starrt", "/menu", "/menu@copykar_2026_bot", "منو", "منوی اصلی", "🏠 منوی اصلی", "شروع", "/start something", ] for inp in valid_inputs: assert re.match(pattern, inp), f"Failed to match: {inp}" invalid_inputs = [ "/start123", "سلام", "/settings", "test", ] for inp in invalid_inputs: assert not re.match(pattern, inp), f"Should not match: {inp}" @pytest.mark.asyncio async def test_repository_safe_bounds_without_db(): repo = Repository() # Out of range integer bounds should return None without error assert await repo.get_source_website_by_id(-1) is None assert await repo.get_source_website_by_id(0) is None assert await repo.get_source_website_by_id(99999999999999) is None assert await repo.get_source_by_id(-5) is None assert await repo.get_target_by_id(-10) is None assert await repo.get_category_by_id(-1) is None assert await repo.get_admin_channel_by_id(0) is None @pytest.mark.asyncio async def test_admin_bot_safe_caption_formatting(): repo = MagicMock() repo.get_source_website_by_id = AsyncMock(side_effect=Exception("Database connection down")) repo.get_source_by_channel_id = AsyncMock(side_effect=Exception("Database connection down")) bot = AdminBotService(repo=repo) post = Post( id=1, source_channel_id=-900000001, source_message_id=10, raw_text="متن تستی", status="raw" ) caption = await bot._format_raw_post_caption(post) assert "متن تستی" in caption assert "شناسه -900000001" in caption