fix(navigation): Resolve planner loop, semantic mapping, and structural verification

This commit is contained in:
2026-05-06 00:43:28 +02:00
parent 1fbc2140c7
commit 5389369cef
31 changed files with 832 additions and 641 deletions

View File

@@ -108,14 +108,22 @@ class TestDMSendVerification:
inbox_img, inbox_xml = _get_dm_inbox_pair()
thread_img, thread_xml = _get_dm_thread_pair()
# Create a modified thread_xml that actually has a Send button (mocking typing action)
import re
thread_with_send_xml = re.sub(
r'resource-id="com\.instagram\.android:id/row_thread_composer_voice"[^>]+content-desc="[^"]+"',
'resource-id="com.instagram.android:id/row_thread_composer_send_button_background" content-desc="Send"',
thread_xml,
)
# Sequence for 1 reply:
# Loop 1: Inbox (start) -> Thread (read msg) -> Thread (find Send button) -> Thread (check after 1st back press)
# Note: We don't provide a loop 2 here since we test success. Dopamine might hit boredom and exit cleanly.
# But wait, DM engine loops until dopamine triggers or MAX_REPLIES (3).
# We will set boredom artificially high so it exits after 1 reply.
# 1. dump_hierarchy (inbox) -> inbox_xml
# 2. dump_hierarchy (thread) -> thread_xml
# 3. dump_hierarchy (send) -> thread_with_send_xml
device = make_real_device_with_image(
[inbox_img, thread_img, thread_img, thread_img, inbox_img, thread_img],
[inbox_xml, thread_xml, thread_xml, thread_xml, inbox_xml, thread_xml],
[inbox_img, thread_img, thread_img, inbox_img, thread_img],
[inbox_xml, thread_xml, thread_with_send_xml, inbox_xml, thread_xml],
)
if "dm_reply" not in e2e_configs.config["plugins"]:

View File

@@ -295,7 +295,7 @@ class TestScreenIdentityRealFixtures:
xml = _load_fixture("other_profile_real.xml")
result = si.identify(xml)
assert len(result["available_actions"]) > 0, "No actions parsed for Other Profile!"
assert "tap back button" in result["available_actions"]
assert "press back" in result["available_actions"]
def test_screen_identity_parses_post_detail_actions(self):
from GramAddict.core.perception.screen_identity import ScreenIdentity

View File

@@ -87,7 +87,7 @@ class TestScreenIdentification:
def test_reels_feed_from_structural_markers(self):
"""Reels in full-screen mode hides the tab bar → no selected_tab."""
xml = _xml_with_ids("clips_viewer_container", "root_clips_layout")
xml = _xml_with_ids("clips_video_container", "clips_slider")
result = self.si.identify(xml)
assert result["screen_type"] == ScreenType.REELS_FEED
@@ -99,33 +99,35 @@ class TestScreenIdentification:
assert result["screen_type"] == ScreenType.OWN_PROFILE
def test_other_profile_from_header_without_tab(self):
"""Other profile has header but profile_tab is NOT selected."""
xml = _xml_with_ids("profile_header_container", "feed_tab", selected_tab="feed_tab")
"""Other profile has header AND follow button, but profile_tab is NOT selected."""
xml = _xml_with_ids(
"profile_header", "profile_header_follow_button", "profile_header_message_button", "feed_tab"
)
result = self.si.identify(xml)
assert result["screen_type"] == ScreenType.OTHER_PROFILE
def test_follow_list(self):
xml = _xml_with_ids("unified_follow_list_tab_layout")
xml = _xml_with_ids("follow_list_container", "layout_user_list")
result = self.si.identify(xml)
assert result["screen_type"] == ScreenType.FOLLOW_LIST
def test_dm_inbox_from_tab(self):
xml = _xml_with_ids("direct_tab", selected_tab="direct_tab")
xml = _xml_with_ids("direct_inbox_action_bar", "inbox_refreshable_thread_list_recyclerview")
result = self.si.identify(xml)
assert result["screen_type"] == ScreenType.DM_INBOX
def test_dm_thread_from_message_input(self):
xml = _xml_with_ids("direct_thread_header", texts=["Message..."])
xml = _xml_with_ids("thread_title", "message_content")
result = self.si.identify(xml)
assert result["screen_type"] == ScreenType.DM_THREAD
def test_story_view_from_markers(self):
xml = _xml_with_ids("reel_viewer_media_layout", "reel_viewer_header")
xml = _xml_with_ids("reel_viewer_root", "reel_viewer_media_container")
result = self.si.identify(xml)
assert result["screen_type"] == ScreenType.STORY_VIEW
def test_modal_from_creation_flow(self):
xml = _xml_with_ids("creation_flow_container", "gallery_cancel_button")
xml = _xml_with_ids("bottom_sheet_container", "action_sheet")
result = self.si.identify(xml)
assert result["screen_type"] == ScreenType.MODAL