diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..fcaaba1
--- /dev/null
+++ b/tests/__init__.py
@@ -0,0 +1 @@
+# Just to make the tests directory a proper Python package
\ No newline at end of file
diff --git a/tests/mock_config.py b/tests/mock_config.py
new file mode 100644
index 0000000..3302cdd
--- /dev/null
+++ b/tests/mock_config.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+def get_settings():
+ """
+ Mock config for testing without requiring TG_API_ID and TG_API_HASH
+ """
+ return {
+ "tg_api_id": 12345,
+ "tg_api_hash": "test_hash",
+ "session_path": "tests/test_data",
+ "api_host": "127.0.0.1",
+ "api_port": 8080,
+ "pyrogram_bridge_url": "http://test.example.com",
+ "log_level": "DEBUG",
+ "debug": False,
+ "token": "test_token",
+ "time_based_merge": False,
+ "show_bridge_link": False,
+ "show_post_flags": True,
+ }
\ No newline at end of file
diff --git a/tests/test_post_parser.py b/tests/test_post_parser.py
new file mode 100644
index 0000000..1875e11
--- /dev/null
+++ b/tests/test_post_parser.py
@@ -0,0 +1,166 @@
+import unittest
+from unittest.mock import MagicMock, PropertyMock, patch
+import re
+import sys
+import os
+# Add project root to sys.path to find post_parser
+sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
+
+# Mock the config module
+sys.modules['config'] = __import__('tests.mock_config', fromlist=['get_settings'])
+
+from pyrogram.types import Message, Document
+from pyrogram.enums import MessageMediaType
+from post_parser import PostParser
+
+class TestPostParserGenerateTitle(unittest.TestCase):
+
+ def setUp(self):
+ self.client_mock = MagicMock()
+ self.parser = PostParser(self.client_mock)
+
+ def tearDown(self):
+ pass
+
+ def _create_mock_message(self, media=None, text=None, caption=None, document_mime_type=None, channel_chat_created=False, web_page=None):
+ message = MagicMock(spec=Message)
+ message.media = media
+ message.text = text
+ message.caption = caption
+ message.web_page = web_page
+ message.channel_chat_created = channel_chat_created
+
+ # Mock document properties if document exists
+ if document_mime_type:
+ doc_mock = MagicMock(spec=Document)
+ type(doc_mock).mime_type = PropertyMock(return_value=document_mime_type)
+ message.document = doc_mock
+ else:
+ message.document = None # Ensure document is None if no mime type provided
+
+ return message
+
+ def test_generate_title_media_photo(self):
+ message = self._create_mock_message(media=MessageMediaType.PHOTO)
+ self.assertEqual(self.parser._generate_title(message), "📷 Photo")
+
+ def test_generate_title_media_video(self):
+ message = self._create_mock_message(media=MessageMediaType.VIDEO)
+ self.assertEqual(self.parser._generate_title(message), "🎥 Video")
+
+ def test_generate_title_media_animation(self):
+ message = self._create_mock_message(media=MessageMediaType.ANIMATION)
+ self.assertEqual(self.parser._generate_title(message), "🎞 GIF")
+
+ def test_generate_title_media_audio(self):
+ message = self._create_mock_message(media=MessageMediaType.AUDIO)
+ self.assertEqual(self.parser._generate_title(message), "🎵 Audio")
+
+ def test_generate_title_media_voice(self):
+ message = self._create_mock_message(media=MessageMediaType.VOICE)
+ self.assertEqual(self.parser._generate_title(message), "🎤 Voice")
+
+ def test_generate_title_media_video_note(self):
+ message = self._create_mock_message(media=MessageMediaType.VIDEO_NOTE)
+ self.assertEqual(self.parser._generate_title(message), "📱 Video circle")
+
+ def test_generate_title_media_sticker(self):
+ message = self._create_mock_message(media=MessageMediaType.STICKER)
+ self.assertEqual(self.parser._generate_title(message), "🎯 Sticker")
+
+ def test_generate_title_media_pdf_document(self):
+ message = self._create_mock_message(media=MessageMediaType.DOCUMENT, document_mime_type='application/pdf')
+ self.assertEqual(self.parser._generate_title(message), "📄 PDF Document")
+
+ def test_generate_title_media_other_document(self):
+ message = self._create_mock_message(media=MessageMediaType.DOCUMENT, document_mime_type='image/jpeg')
+ self.assertEqual(self.parser._generate_title(message), "📎 Document")
+
+ def test_generate_title_channel_created(self):
+ message = self._create_mock_message(channel_chat_created=True)
+ self.assertEqual(self.parser._generate_title(message), "✨ Channel created")
+
+ def test_generate_title_text_only(self):
+ message = self._create_mock_message(text="This is the first line.\nThis is the second line.")
+ self.assertEqual(self.parser._generate_title(message), "This is the first line.\nThis is the second line.")
+
+ def test_generate_title_text_with_html(self):
+ message = self._create_mock_message(text="Bold text first line.\nItalic second line.")
+ self.assertEqual(self.parser._generate_title(message), "Bold text first line.\nItalic second line.")
+
+ def test_generate_title_text_with_url_and_text(self):
+ message = self._create_mock_message(text="Check out this link: https://example.com")
+ self.assertEqual(self.parser._generate_title(message), "Check out this link:") # URL is stripped
+
+ def test_generate_title_text_only_url(self):
+ message = self._create_mock_message(text="https://example.com")
+ self.assertEqual(self.parser._generate_title(message), "🔗 Web link")
+
+ def test_generate_title_text_only_youtube_url(self):
+ message = self._create_mock_message(text="https://www.youtube.com/watch?v=dQw4w9WgXcQ")
+ self.assertEqual(self.parser._generate_title(message), "🎥 YouTube Link")
+
+ def test_generate_title_text_only_youtu_be_url(self):
+ message = self._create_mock_message(text="https://youtu.be/dQw4w9WgXcQ")
+ self.assertEqual(self.parser._generate_title(message), "🎥 YouTube Link")
+
+ def test_generate_title_caption_with_url_and_text(self):
+ message = self._create_mock_message(media=MessageMediaType.PHOTO, caption="Look at this photo! https://example.com/image.jpg")
+ # Media takes priority
+ self.assertEqual(self.parser._generate_title(message), "📷 Photo")
+
+ def test_generate_title_long_text_trimming(self):
+ long_text = "This is a very long line of text that definitely exceeds the maximum length allowed for a title, so it should be trimmed intelligently at the last space before the limit."
+ message = self._create_mock_message(text=long_text)
+ expected_title = "This is a very long line of text that definitely exceeds the maximum length allowed for a title, so..."
+ self.assertEqual(self.parser._generate_title(message), expected_title)
+
+ def test_generate_title_long_text_no_space_trimming(self):
+ long_text = "Thisisaverylonglineoftextthatdefinitelyexceedsthemaximumlengthallowedforatitlesoitshouldbetrimmedatthelimitbecausehasnospaces."
+ message = self._create_mock_message(text=long_text)
+ expected_title = "Thisisaverylonglineoftextthatdefinitelyexceedsthemaximumlengthallowedforatitlesoitshouldbetrimmedatt..."
+ self.assertEqual(self.parser._generate_title(message), expected_title)
+
+ def test_generate_title_text_with_only_html_and_urls(self):
+ message = self._create_mock_message(text="Link https://another.link")
+ self.assertEqual(self.parser._generate_title(message), "