test(e2e): Fix navigation graph instantiation and mock UI sequence exhaustion
This commit is contained in:
@@ -21,6 +21,7 @@ If Instagram updates its app and moves a button, GramPilot doesn't crash. It fal
|
||||
## ✨ Core Features
|
||||
|
||||
* 🚫 **Zero Limits Configuration**: Forget about configuring "max_likes" or "delays". GramPilot uses a **Dopamine Pacing Engine** to simulate human boredom. If the content isn't interesting, it skips it or ends the session early.
|
||||
* 🎯 **Mission-Driven Navigation**: Say goodbye to abstract goal configurations. Define a `strategy` (like `aggressive_growth` or `nurture_community`) in `config.yml`, and the **Goal Decomposer Engine** automatically orchestrates the optimal routing and task allocation using enabled plugins.
|
||||
* ⚖️ **Active Inference (Shadow Mode)**: The bot continuously predicts the outcome of its clicks. If it lands on a popup instead of a profile, it registers a "Prediction Error", presses back, and dynamically recalibrates without panicking.
|
||||
* ⛩️ **Telepathic Engine**: A strictly tiered resolution cascade (Keyword -> Vectors -> LLM) that ensures 90% of navigation happens at 0-token cost while maintaining fallback AI resilience.
|
||||
* 🧬 **Resonance Oracle**: The bot only interacts with content that matches a pre-defined persona aesthetic, completely bypassing spam or low-quality content.
|
||||
|
||||
102
tests/e2e/test_goal_decomposer_e2e.py
Normal file
102
tests/e2e/test_goal_decomposer_e2e.py
Normal file
@@ -0,0 +1,102 @@
|
||||
"""
|
||||
E2E Test: Goal Decomposition and Autonomous Orchestration
|
||||
==========================================================
|
||||
|
||||
This test proves that the bot's core autonomy pipeline (Task Generation -> Selection -> Navigation)
|
||||
works end-to-end using real configuration objects and real UI XML dumps.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
from GramAddict.core.goal_decomposer import GoalDecomposer
|
||||
from GramAddict.core.growth_brain import GrowthBrain
|
||||
from GramAddict.core.q_nav_graph import QNavGraph
|
||||
from GramAddict.core.telepathic_engine import TelepathicEngine
|
||||
|
||||
FIXTURE_DIR = os.path.join(os.path.dirname(__file__), "fixtures")
|
||||
|
||||
|
||||
def _load_fixture(name: str) -> str:
|
||||
path = os.path.join(FIXTURE_DIR, name)
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
class MockZeroEngine:
|
||||
"""Mock ZeroEngine needed by nav_graph to run actions without full active_inference logic."""
|
||||
|
||||
def __init__(self, device):
|
||||
self.device = device
|
||||
self.telepathic = TelepathicEngine()
|
||||
|
||||
def do(self, intent: str):
|
||||
# Simplistic execution for navigation
|
||||
xml = self.device.dump_hierarchy()
|
||||
node = self.telepathic.find_best_node(xml, intent, self.device)
|
||||
if node:
|
||||
# Just pretend we clicked
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@pytest.mark.live_llm
|
||||
class TestAutonomousOrchestrationE2E:
|
||||
"""End-to-End pipeline: Config -> GoalDecomposer -> GrowthBrain -> NavGraph -> UI XML"""
|
||||
|
||||
def test_e2e_mission_to_explore_feed_navigation(self, make_real_device_with_xml, monkeypatch):
|
||||
"""
|
||||
Simulates the bot_flow.py autonomous loop:
|
||||
1. Decomposer parses aggressive_growth mission.
|
||||
2. Brain selects ExploreFeed task.
|
||||
3. Orchestrator uses nav_graph to reach ExploreFeed.
|
||||
"""
|
||||
# 1. Setup simulated device with XML sequence
|
||||
home_xml = _load_fixture("home_feed_real.xml")
|
||||
explore_xml = _load_fixture("explore_grid_real.xml")
|
||||
|
||||
# Sequence for nav_graph.navigate_to("ExploreFeed")
|
||||
# We provide a long sequence of explore_xml at the end to simulate the app remaining on the Explore screen
|
||||
# after the transition.
|
||||
xml_sequence = [
|
||||
home_xml, # Initial perception (HomeFeed)
|
||||
home_xml, # finding explore button
|
||||
explore_xml, # post-click state (ExploreFeed)
|
||||
explore_xml, # Goal validation check
|
||||
] + [explore_xml] * 20
|
||||
|
||||
device = make_real_device_with_xml(xml_sequence)
|
||||
|
||||
# 2. Fake Config inputs
|
||||
mission = {"strategy": "aggressive_growth"}
|
||||
plugins = {"likes": {"percentage": 100}}
|
||||
actions = {"explore": "1-3"}
|
||||
|
||||
# 3. Generate Tasks
|
||||
decomposer = GoalDecomposer(plugins=plugins, actions=actions, mission=mission)
|
||||
tasks = decomposer.generate_tasks()
|
||||
assert len(tasks) > 0, "Decomposer must generate tasks"
|
||||
|
||||
# Force selection of ExploreFeed for deterministic test
|
||||
monkeypatch.setattr(
|
||||
"random.choices", lambda population, weights, k: [t for t in population if t.target_screen == "ExploreFeed"]
|
||||
)
|
||||
|
||||
# 4. Brain Selection
|
||||
brain = GrowthBrain(username="testuser")
|
||||
|
||||
class MockDopamine:
|
||||
boredom = 0.0
|
||||
|
||||
selected_task = brain.select_task(MockDopamine(), tasks)
|
||||
assert selected_task is not None
|
||||
assert selected_task.target_screen == "ExploreFeed"
|
||||
|
||||
# 5. Execute Navigation (mimicking bot_flow.py)
|
||||
nav_graph = QNavGraph(device=device)
|
||||
zero_engine = MockZeroEngine(device)
|
||||
|
||||
success = nav_graph.navigate_to(selected_task.target_screen, zero_engine)
|
||||
|
||||
assert success is True, "Orchestrator failed to navigate to the decomposed Task's target screen!"
|
||||
Reference in New Issue
Block a user