test_delivery.py
1 """Tests for the delivery routing module.""" 2 3 from gateway.config import Platform 4 from gateway.delivery import DeliveryTarget 5 from gateway.session import SessionSource 6 7 8 class TestParseTargetPlatformChat: 9 def test_explicit_telegram_chat(self): 10 target = DeliveryTarget.parse("telegram:12345") 11 assert target.platform == Platform.TELEGRAM 12 assert target.chat_id == "12345" 13 assert target.is_explicit is True 14 15 def test_platform_only_no_chat_id(self): 16 target = DeliveryTarget.parse("discord") 17 assert target.platform == Platform.DISCORD 18 assert target.chat_id is None 19 assert target.is_explicit is False 20 21 def test_local_target(self): 22 target = DeliveryTarget.parse("local") 23 assert target.platform == Platform.LOCAL 24 assert target.chat_id is None 25 26 def test_origin_with_source(self): 27 origin = SessionSource(platform=Platform.TELEGRAM, chat_id="789", thread_id="42") 28 target = DeliveryTarget.parse("origin", origin=origin) 29 assert target.platform == Platform.TELEGRAM 30 assert target.chat_id == "789" 31 assert target.thread_id == "42" 32 assert target.is_origin is True 33 34 def test_origin_without_source(self): 35 target = DeliveryTarget.parse("origin") 36 assert target.platform == Platform.LOCAL 37 assert target.is_origin is True 38 39 def test_unknown_platform(self): 40 target = DeliveryTarget.parse("unknown_platform") 41 assert target.platform == Platform.LOCAL 42 43 44 class TestTargetToStringRoundtrip: 45 def test_origin_roundtrip(self): 46 origin = SessionSource(platform=Platform.TELEGRAM, chat_id="111", thread_id="42") 47 target = DeliveryTarget.parse("origin", origin=origin) 48 assert target.to_string() == "origin" 49 50 def test_local_roundtrip(self): 51 target = DeliveryTarget.parse("local") 52 assert target.to_string() == "local" 53 54 def test_platform_only_roundtrip(self): 55 target = DeliveryTarget.parse("discord") 56 assert target.to_string() == "discord" 57 58 def test_explicit_chat_roundtrip(self): 59 target = DeliveryTarget.parse("telegram:999") 60 s = target.to_string() 61 assert s == "telegram:999" 62 63 reparsed = DeliveryTarget.parse(s) 64 assert reparsed.platform == Platform.TELEGRAM 65 assert reparsed.chat_id == "999" 66 67 68 class TestCaseSensitiveChatIdParsing: 69 """Test that chat IDs preserve their original case (issue #11768).""" 70 71 def test_slack_uppercase_chat_id_preserved(self): 72 """Slack channel IDs like C123ABC should preserve case.""" 73 target = DeliveryTarget.parse("slack:C123ABC") 74 assert target.platform == Platform.SLACK 75 assert target.chat_id == "C123ABC" # Should NOT be lowercased to c123abc 76 assert target.is_explicit is True 77 78 def test_slack_chat_id_with_thread_preserved(self): 79 """Slack channel:thread IDs should preserve case.""" 80 target = DeliveryTarget.parse("slack:C123ABC:thread123") 81 assert target.platform == Platform.SLACK 82 assert target.chat_id == "C123ABC" 83 assert target.thread_id == "thread123" 84 85 def test_matrix_room_id_preserved(self): 86 """Matrix room IDs like !RoomABC:example.org should preserve case. 87 88 Note: Matrix room IDs contain colons (e.g., !RoomABC:example.org). 89 Due to the platform:chat_id:thread_id format, these are parsed as 90 chat_id=!RoomABC and thread_id=example.org. This is a known limitation 91 of the current format. The fix preserves case but doesn't change the 92 parsing structure. 93 """ 94 target = DeliveryTarget.parse("matrix:!RoomABC:example.org") 95 assert target.platform == Platform.MATRIX 96 # The room ID is split at the first colon after the platform prefix 97 # This is a format limitation - the case is preserved but the structure is split 98 assert target.chat_id == "!RoomABC" 99 assert target.thread_id == "example.org" 100 101 def test_mixed_case_chat_id_roundtrip(self): 102 """Mixed-case chat IDs should survive parse-to_string roundtrip.""" 103 original = "telegram:ChatId123ABC" 104 target = DeliveryTarget.parse(original) 105 s = target.to_string() 106 reparsed = DeliveryTarget.parse(s) 107 assert reparsed.chat_id == "ChatId123ABC" 108 109 110 class TestPlatformNameCaseInsensitivity: 111 """Test that platform names are case-insensitive.""" 112 113 def test_uppercase_platform_name(self): 114 """Platform names should be case-insensitive.""" 115 target = DeliveryTarget.parse("TELEGRAM:12345") 116 assert target.platform == Platform.TELEGRAM 117 assert target.chat_id == "12345" 118 119 def test_mixed_case_platform_name(self): 120 """Mixed-case platform names should work.""" 121 target = DeliveryTarget.parse("TeleGram:12345") 122 assert target.platform == Platform.TELEGRAM 123 assert target.chat_id == "12345" 124 125 126