import pytest import logging import os from unittest.mock import MagicMock MagicMock.app_id = "com.instagram.android" MagicMock._get_current_app = MagicMock(return_value="com.instagram.android") class MockArgs: def __init__(self, **kwargs): for k, v in kwargs.items(): setattr(self, k, v) class MockConfigs: def __init__(self, args): self.args = args class MockDeviceV2: def __init__(self): self.clicks = [] self.shells = [] self.double_clicks = [] self.presses = [] self.xml_dump = "" def click(self, x, y): self.clicks.append((x, y)) self.xml_dump += f"" def shell(self, cmd): self.shells.append(cmd) def double_click(self, x, y, duration=0): self.double_clicks.append((x, y)) def press(self, key): self.presses.append(key) def dump_hierarchy(self): return self.xml_dump class MockDevice: def __init__(self): self.deviceV2 = MockDeviceV2() self.app_id = "com.instagram.android" def _get_current_app(self): return "com.instagram.android" def get_info(self): return {"displayWidth": 1080, "displayHeight": 2400} def cm_to_pixels(self, cm): return cm * 10 def dump_hierarchy(self): return self.deviceV2.dump_hierarchy() def click(self, x=None, y=None, obj=None): if obj: x, y = obj.get("x", 0), obj.get("y", 0) self.deviceV2.click(x, y) class MockTelepathicEngine: def find_best_node(self, xml, intent_description, device=None, **kwargs): description = intent_description.lower() if "story ring" in description: return {"x": 100, "y": 100, "description": "Story Ring", "score": 1.0} if "follow" in description or "folgen" in description: return {"x": 200, "y": 200, "text": "Follow", "description": "Follow Button", "score": 1.0} if "first image" in description or "profile grid" in description: return {"x": 300, "y": 300, "description": "Grid Image", "score": 1.0} return None def _extract_semantic_nodes(self, xml, intent=None, threshold=0.0): return [{"x": 10, "y": 10, "semantic_string": "mock node", "area": 100}] def _keyword_match_score(self, intent, nodes): if nodes: return {"semantic": nodes[0].get("semantic_string"), "score": 0.9, "node": nodes[0]} return None def _cosine_similarity(self, v1, v2): return 0.9 def verify_success(self, intent_description, post_click_xml, previous_state_xml=None): return True def confirm_click(self, *args, **kwargs): pass def reject_click(self, *args, **kwargs): pass def classify_screen_content(self, xml, target_class): # Default mock behavior: assume it matches if it's not obviously trash return "organic" def get_active_engagement(self): return {"type": "like", "confidence": 0.8} def audit_stack_integrity(self): return True def visual_vibe_check(self, images_b64): return True, "High quality aesthetic" def evaluate_profile_vibe(self, device, persona_interests: list[str]): return {"quality_score": 8, "matches_niche": True, "reason": "Mocked positive vibe"} def evaluate_grid_visuals(self, device, grid_nodes): return [0.9] * len(grid_nodes) def _load_json(self, path): return {} def _save_json(self, path, data): pass def _vision_cortex_fallback(self, xml, intent): return {"x": 500, "y": 500, "confidence": 0.7} @classmethod def get_instance(cls): return cls() @pytest.fixture def mock_logger(): return logging.getLogger("test") @pytest.fixture def device(): return MockDevice() @pytest.fixture(autouse=True) def reset_singletons(): """Ensure all core engine singletons are fresh for each test.""" from GramAddict.core.telepathic_engine import TelepathicEngine from GramAddict.core.goap import GoalExecutor from GramAddict.core.situational_awareness import SituationalAwarenessEngine TelepathicEngine.reset() GoalExecutor.reset() SituationalAwarenessEngine.reset() # Aggressively wipe on-disk session files to prevent state leakage in tests for f in ["telepathic_memory.json", "telepathic_blacklist.json", "growth_brain_memory.json", "gramaddict_nav_map.json", "l2_channels_cache.json"]: if os.path.exists(f): try: os.remove(f) except Exception: pass yield @pytest.fixture(autouse=True) def telepathic_mock(monkeypatch): import GramAddict.core.telepathic_engine engine = MockTelepathicEngine() monkeypatch.setattr(GramAddict.core.telepathic_engine.TelepathicEngine, "get_instance", lambda: engine) return engine @pytest.fixture def mock_cognitive_stack(): stack = { "dopamine": MagicMock(), "darwin": MagicMock(), "resonance": MagicMock(), "active_inference": MagicMock(), "growth_brain": MagicMock(), "swarm": MagicMock(), "radome": MagicMock(), "nav_graph": MagicMock(), "zero_engine": MagicMock(), "crm": MagicMock(), "telepathic": MockTelepathicEngine() } stack["radome"].sanitize_xml.side_effect = lambda x: x return stack