from __future__ import annotations from unittest.mock import MagicMock, patch import pytest from yuxi.channels.adapters.whatsapp.reactions.ack_reaction import AckReactionManager from yuxi.channels.adapters.whatsapp.reactions.reaction_level import ReactionLevel, ReactionLevelController from yuxi.channels.adapters.whatsapp.markdown import markdown_to_whatsapp, text_sanitizer from yuxi.channels.adapters.whatsapp.structured_context import ( ContextSource, ContextType, StructuredContextEntry, UntrustedStructuredContext, ) class TestReactionLevel: def test_enum_values(self): assert ReactionLevel.OFF == "off" assert ReactionLevel.MINIMAL == "minimal" assert ReactionLevel.FULL == "full" class TestReactionLevelController: def test_default_constructor(self): ctrl = ReactionLevelController({}) assert ctrl.level == ReactionLevel.MINIMAL def test_off_level(self): ctrl = ReactionLevelController({"reactionLevel": "off"}) assert ctrl.level == ReactionLevel.OFF assert ctrl.can_send_reaction() is False assert ctrl.can_send_reaction(is_ack=True) is False def test_minimal_level(self): ctrl = ReactionLevelController({"reactionLevel": "minimal"}) assert ctrl.level == ReactionLevel.MINIMAL assert ctrl.can_send_reaction() is False assert ctrl.can_send_reaction(is_ack=True) is True def test_full_level(self): ctrl = ReactionLevelController({"reactionLevel": "full"}) assert ctrl.level == ReactionLevel.FULL assert ctrl.can_send_reaction() is True assert ctrl.can_send_reaction(is_ack=True) is True def test_invalid_level_defaults(self): ctrl = ReactionLevelController({"reactionLevel": "invalid"}) assert ctrl.level == ReactionLevel.MINIMAL def test_agent_reactions_disabled(self): ctrl = ReactionLevelController({"reactionLevel": "full", "agentReactionsEnabled": False}) assert ctrl.agent_reactions_enabled is False assert ctrl.can_agent_react() is False def test_agent_reactions_off_level(self): ctrl = ReactionLevelController({"reactionLevel": "off", "agentReactionsEnabled": True}) assert ctrl.can_agent_react() is False def test_agent_reactions_enabled(self): ctrl = ReactionLevelController({"reactionLevel": "full", "agentReactionsEnabled": True}) assert ctrl.can_agent_react() is True def test_agent_reaction_guidance(self): ctrl = ReactionLevelController({"agentReactionGuidance": "Use emoji"}) assert ctrl.get_agent_guidance() == "Use emoji" def test_agent_reaction_guidance_empty(self): ctrl = ReactionLevelController({}) assert ctrl.agent_reaction_guidance == "" def test_agent_reaction_guidance_none(self): ctrl = ReactionLevelController({}) assert ctrl.get_agent_guidance() is None def test_properties_readonly(self): ctrl = ReactionLevelController({"reactionLevel": "full"}) assert ctrl.level == ReactionLevel.FULL assert ctrl.agent_reactions_enabled is True class TestAckReactionManager: def test_default_constructor(self): mgr = AckReactionManager({}) assert mgr.emoji == "\u2705" assert mgr.should_ack_direct() is True assert mgr.should_ack_group() is True def test_custom_emoji(self): mgr = AckReactionManager({"ackReaction": {"emoji": "👍"}}) assert mgr.emoji == "👍" def test_direct_disabled(self): mgr = AckReactionManager({"ackReaction": {"direct": False}}) assert mgr.should_ack_direct() is False def test_group_off(self): mgr = AckReactionManager({"ackReaction": {"group": "off"}}) assert mgr.should_ack_group() is False def test_group_mentions_only(self): mgr = AckReactionManager({"ackReaction": {"group": "mentions"}}) assert mgr.should_ack_group() is True assert mgr.should_ack_group_mentions_only() is True def test_can_ack_direct(self): mgr = AckReactionManager({"ackReaction": {"cooldown": 0}}) assert mgr.can_ack("chat1", is_group=False) is True def test_can_ack_group_full(self): mgr = AckReactionManager({"ackReaction": {"group": "full", "cooldown": 0}}) assert mgr.can_ack("chat1", is_group=True) is True def test_can_ack_group_mentions_only_mentioned(self): mgr = AckReactionManager({"ackReaction": {"group": "mentions", "cooldown": 0}}) assert mgr.can_ack("chat1", is_group=True, is_mentioned=True) is True def test_can_ack_group_mentions_only_not_mentioned(self): mgr = AckReactionManager({"ackReaction": {"group": "mentions", "cooldown": 0}}) assert mgr.can_ack("chat1", is_group=True, is_mentioned=False) is False def test_can_ack_group_off(self): mgr = AckReactionManager({"ackReaction": {"group": "off"}}) assert mgr.can_ack("chat1", is_group=True) is False def test_can_ack_direct_disabled(self): mgr = AckReactionManager({"ackReaction": {"direct": False, "cooldown": 0}}) assert mgr.can_ack("chat1", is_group=False) is False def test_cooldown_prevents_ack(self): mgr = AckReactionManager({"ackReaction": {"cooldown": 60}}) assert mgr.can_ack("chat1", is_group=False) is True mgr.record_ack("chat1") assert mgr.can_ack("chat1", is_group=False) is False def test_different_chats_independent_cooldown(self): mgr = AckReactionManager({"ackReaction": {"cooldown": 60}}) assert mgr.can_ack("chat1", is_group=False) is True mgr.record_ack("chat1") assert mgr.can_ack("chat2", is_group=False) is True def test_record_ack(self): mgr = AckReactionManager({}) mgr.record_ack("chat1") class TestTextSanitizer: def test_empty_string(self): assert text_sanitizer("") == "" def test_none_like(self): assert text_sanitizer("") == "" def test_nbsp_replacement(self): assert text_sanitizer("hello world") == "hello world" def test_allows_b_tag(self): assert text_sanitizer("bold") == "bold" def test_allows_i_tag(self): assert text_sanitizer("italic") == "italic" def test_allows_strong_tag(self): assert text_sanitizer("bold") == "bold" def test_allows_em_tag(self): assert text_sanitizer("em") == "em" def test_allows_u_tag(self): assert text_sanitizer("underline") == "underline" def test_allows_s_tag(self): assert text_sanitizer("strikethrough") == "strikethrough" def test_allows_code_tag(self): assert text_sanitizer("code") == "code" def test_allows_pre_tag(self): assert text_sanitizer("
pre
") == "
pre
" def test_allows_a_tag(self): assert text_sanitizer('link') == 'link' def test_strips_script_tag(self): result = text_sanitizer("") assert "" not in result def test_strips_unknown_tags(self): assert text_sanitizer("
text
") == "text" assert text_sanitizer("text") == "text" def test_strips_mixed_allowed_disallowed(self): result = text_sanitizer("safe") assert "safe" in result assert "