This commit is contained in:
2026-04-17 00:44:41 +02:00
parent fa1d01527d
commit 89f14463c5
42 changed files with 2452 additions and 314 deletions

View File

@@ -0,0 +1,49 @@
import pytest
from unittest.mock import MagicMock, patch
from GramAddict.core.q_nav_graph import QNavGraph
@pytest.fixture
def mock_device():
device = MagicMock()
device.app_id = "com.instagram.android"
device.deviceV2 = MagicMock()
# Mock current app to be Instagram
device._get_current_app.return_value = "com.instagram.android"
return device
def test_recovery_from_dm_view(mock_device):
"""
Test Case: Bot starts in a DM thread (UNKNOWN state).
It wants to go to ReelsFeed.
Global nav bar is missing in DMs, so first 'tap_reels_tab' will fail.
Bot should then press 'back' and try again.
"""
nav = QNavGraph(mock_device)
nav.current_state = "UNKNOWN"
# Sequence of dumps (exactly 1 per failed attempt, 2 per successful attempt):
# 1. Attempt 1 (DM): _execute_transition calls dump(1) -> find_best_node returns None -> Returns False
# 2. QNavGraph calls press("back")
# 3. Attempt 2 (Home): _execute_transition calls dump(2) -> find_best_node returns Node
# 4. _execute_transition calls dump(3) -> post-click != pre-click -> Returns True
mock_device.deviceV2.dump_hierarchy.side_effect = ["<DM />", "<Home />", "<ReelsFeed />"]
zero_engine = MagicMock()
with patch('GramAddict.core.telepathic_engine.TelepathicEngine.get_instance') as mock_get:
mock_engine = MagicMock()
mock_get.return_value = mock_engine
# 1st call: DM (nothing found)
# 2nd call: Home (reels tab found)
mock_engine.find_best_node.side_effect = [None, {"x": 50, "y": 50, "score": 0.95, "source": "keyword"}]
success = nav.navigate_to("ReelsFeed", zero_engine)
# Verify
assert success is True
assert nav.current_state == "ReelsFeed"
# Verify recovery was triggered
mock_device.deviceV2.press.assert_called_with("back")
assert mock_device.deviceV2.dump_hierarchy.call_count == 3

View File

@@ -41,6 +41,8 @@ class TestNodeExtraction:
"""
engine = TelepathicEngine()
xml = load_fixture("home_feed_with_ad.xml")
# Test raw extraction (backward compatibility)
nodes = engine._extract_semantic_nodes(xml)
like_nodes = [n for n in nodes if "row feed button like" in n["semantic_string"]]