# -*- coding: utf-8 -*- """Gezielte Tests: roter Nachrichten-Badge scrollt zur ersten ungelesenen Nachricht.""" from __future__ import annotations import inspect import re import unittest from pathlib import Path ROOT = Path(__file__).resolve().parent HTML = (ROOT / "web" / "empfang.html").read_text(encoding="utf-8-sig") def _func_body(src: str, name: str) -> str: marker = f"function {name}" idx = src.find(marker) if idx < 0: return "" rest = src[idx + len(marker) :] nxt = rest.find("\nfunction ") return rest[:nxt] if nxt >= 0 else rest class MessageBadgeScrollTests(unittest.TestCase): @classmethod def setUpClass(cls): cls.html = HTML cls.nav = _func_body(cls.html, "navigateFromMessagesBadgeClick") cls.render = _func_body(cls.html, "renderMessengerConversation") cls.task_nav = _func_body(cls.html, "navigateFromTaskBadgeClick") def test_badge_has_click_handler(self): self.assertIn("navigateFromMessagesBadgeClick()", self.html) self.assertIn("sb-me-pill-msgs", self.html) def test_uses_peer_user_id(self): self.assertIn("findFirstPeerWithPendingAck", self.nav) self.assertIn("hit.uid", self.nav) self.assertIn("selectDmPeer", self.nav) def test_first_unread_message_id(self): self.assertIn("findFirstUnreadMessageIdForPeer", self.html) self.assertIn("messageNeedsAlarmAck", _func_body(self.html, "findFirstUnreadMessageIdForPeer")) def test_dm_open_msg_id_in_kontakt_panel(self): kp = _func_body(self.html, "kontaktPanelOpenMessagesBadgeInHuelle") self.assertIn("dm_open_msg_id", kp) self.assertIn("/shell/dm-open", kp) self.assertIn("focus_empfang_chat_shell", kp) self.assertIn("kontaktPanelOpenMessagesBadgeInHuelle", self.nav) def test_arm_pending_scroll(self): self.assertIn("armEmpfangBadgeScrollToUnread", self.nav) self.assertIn("consumeEmpfangBadgeScrollForActivePeer", self.render) def test_scroll_after_render_not_blind_timeout(self): self.assertIn("scrollMessengerToMessageIdWithRetry", self.html) self.assertNotIn("setTimeout(function() { scrollMessengerToMessageId(dmMid); }, 720)", self.html) body = _func_body(self.html, "scrollMessengerToMessageIdWithRetry") self.assertIn("maxTries", body) self.assertIn("messengerMessageElementForId", body) def test_scroll_into_view(self): body = _func_body(self.html, "scrollMessengerToMessageIdWithRetry") self.assertIn("scrollIntoView", body) def test_fallback_bottom(self): body = _func_body(self.html, "scrollMessengerToMessageIdWithRetry") self.assertIn("fallbackBottom", body) self.assertIn("scrollMessengerToBottom", body) def test_no_infinite_loop(self): body = _func_body(self.html, "scrollMessengerToMessageIdWithRetry") self.assertIn("tries >= maxTries", body) self.assertNotIn("setInterval", body) def test_stable_message_id_selector(self): self.assertIn("data-msg-id", _func_body(self.html, "messengerMessageElementForId")) def test_message_involves_peer_by_uid(self): body = _func_body(self.html, "messageInvolvesPeerUid") self.assertIn("direct_conv_key", body) self.assertIn("sender_user_id", body) def test_kontakt_and_chat_same_nav_function(self): self.assertIn("isKontaktPanelMode()", self.nav) self.assertIn("selectDmPeer", self.nav) def test_task_badge_unchanged(self): self.assertIn("kontaktPanelNavigateFromBadge", self.task_nav) self.assertNotIn("findFirstUnreadMessageIdForPeer", self.task_nav) def test_ack_helpers_unchanged(self): self.assertIn("function messageHasChatAckEffective", self.html) self.assertIn("function messageNeedsAlarmAck", self.html) def test_chronological_first_unread(self): body = _func_body(self.html, "findFirstUnreadMessageIdForPeer") self.assertIn("messengerChronoSorted", body) def test_shell_context_uses_arm_not_timeout(self): ctx = _func_body(self.html, "refreshDesktopShellContextFromServer") self.assertIn("armEmpfangBadgeScrollToUnread", ctx) class EmpfangHtmlSyntaxSmoke(unittest.TestCase): def test_no_obvious_script_tag_break(self): scripts = re.findall(r"]*>([\s\S]*?)", HTML, flags=re.I) self.assertGreater(len(scripts), 0) for block in scripts: if "navigateFromMessagesBadgeClick" in block: self.assertIn("function navigateFromMessagesBadgeClick", block) break else: self.fail("navigateFromMessagesBadgeClick script block missing") if __name__ == "__main__": unittest.main()