WIP: Regression hell
This commit is contained in:
@@ -123,7 +123,7 @@ def mock_app() -> Generator[App, None, None]:
|
||||
'projects': {'paths': [], 'active': ''},
|
||||
'gui': {'show_windows': {}}
|
||||
}),
|
||||
patch('src.gui_2.save_config'),
|
||||
patch('src.models.save_config'),
|
||||
patch('src.gui_2.project_manager'),
|
||||
patch('src.gui_2.session_logger'),
|
||||
patch('src.gui_2.immapp.run'),
|
||||
@@ -155,7 +155,7 @@ def app_instance() -> Generator[App, None, None]:
|
||||
'projects': {'paths': [], 'active': ''},
|
||||
'gui': {'show_windows': {}}
|
||||
}),
|
||||
patch('src.gui_2.save_config'),
|
||||
patch('src.models.save_config'),
|
||||
patch('src.gui_2.project_manager'),
|
||||
patch('src.gui_2.session_logger'),
|
||||
patch('src.gui_2.immapp.run'),
|
||||
|
||||
@@ -34,10 +34,15 @@ def test_conductor_engine_run_executes_tickets_in_order(monkeypatch: pytest.Monk
|
||||
# Mocking lifecycle to mark ticket as complete so dependencies can be resolved
|
||||
|
||||
def side_effect(ticket, context, *args, **kwargs):
|
||||
ticket.mark_complete()
|
||||
import threading
|
||||
def do_work():
|
||||
import time
|
||||
time.sleep(0.1)
|
||||
ticket.mark_complete()
|
||||
threading.Thread(target=do_work).start()
|
||||
return "Success"
|
||||
mock_lifecycle.side_effect = side_effect
|
||||
engine.run()
|
||||
engine.run(max_ticks=20)
|
||||
|
||||
vlogger.log_state("T1 Status Final", "todo", ticket1.status)
|
||||
vlogger.log_state("T2 Status Final", "todo", ticket2.status)
|
||||
@@ -108,8 +113,8 @@ def test_run_worker_lifecycle_context_injection(monkeypatch: pytest.MonkeyPatch)
|
||||
run_worker_lifecycle(ticket, context, context_files=context_files)
|
||||
# Verify ASTParser calls:
|
||||
# First file (primary) should get curated view, others (secondary) get skeleton
|
||||
mock_ast_parser.get_curated_view.assert_called_once_with("def primary(): pass")
|
||||
mock_ast_parser.get_skeleton.assert_called_once_with("def secondary(): pass")
|
||||
mock_ast_parser.get_curated_view.assert_called_once_with("def primary(): pass", path="primary.py")
|
||||
mock_ast_parser.get_skeleton.assert_called_once_with("def secondary(): pass", path="secondary.py")
|
||||
# Verify user_message contains the views
|
||||
_, kwargs = mock_send.call_args
|
||||
user_message = kwargs["user_message"]
|
||||
@@ -238,10 +243,15 @@ def test_conductor_engine_dynamic_parsing_and_execution(monkeypatch: pytest.Monk
|
||||
# Mock run_worker_lifecycle to mark tickets as complete
|
||||
with patch("src.multi_agent_conductor.run_worker_lifecycle") as mock_lifecycle:
|
||||
def side_effect(ticket, context, *args, **kwargs):
|
||||
ticket.mark_complete()
|
||||
import threading
|
||||
def do_work():
|
||||
import time
|
||||
time.sleep(0.1)
|
||||
ticket.mark_complete()
|
||||
threading.Thread(target=do_work).start()
|
||||
return "Success"
|
||||
mock_lifecycle.side_effect = side_effect
|
||||
engine.run()
|
||||
engine.run(max_ticks=20)
|
||||
assert mock_lifecycle.call_count == 3
|
||||
# Verify dependency order: T1 must be called before T2
|
||||
calls = [call[0][0].id for call in mock_lifecycle.call_args_list]
|
||||
|
||||
@@ -111,3 +111,55 @@ def test_deepseek_streaming(mock_post: MagicMock) -> None:
|
||||
|
||||
result = ai_client.send(md_content="Context", user_message="Stream test", base_dir=".", stream=True)
|
||||
assert result == "Hello World"
|
||||
|
||||
@patch("requests.post")
|
||||
def test_deepseek_payload_verification(mock_post: MagicMock) -> None:
|
||||
"""
|
||||
Verifies that the correct JSON payload (tools, history, params) is sent to DeepSeek.
|
||||
"""
|
||||
ai_client.set_provider("deepseek", "deepseek-chat")
|
||||
ai_client.reset_session()
|
||||
with patch("src.ai_client._load_credentials", return_value={"deepseek": {"api_key": "test-key"}}):
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.return_value = {
|
||||
"choices": [{"message": {"content": "OK"}, "finish_reason": "stop"}]
|
||||
}
|
||||
mock_post.return_value = mock_response
|
||||
|
||||
ai_client.send(md_content="Context", user_message="Message 1", base_dir=".", discussion_history="History")
|
||||
|
||||
args, kwargs = mock_post.call_args
|
||||
payload = kwargs["json"]
|
||||
|
||||
assert payload["model"] == "deepseek-chat"
|
||||
assert "tools" in payload
|
||||
assert len(payload["messages"]) == 2 # system + user
|
||||
assert "[DISCUSSION HISTORY]\n\nHistory" in payload["messages"][1]["content"]
|
||||
assert "temperature" in payload
|
||||
assert "max_tokens" in payload
|
||||
|
||||
@patch("requests.post")
|
||||
def test_deepseek_reasoner_payload_verification(mock_post: MagicMock) -> None:
|
||||
"""
|
||||
Verifies that deepseek-reasoner payload excludes tools and temperature.
|
||||
"""
|
||||
ai_client.set_provider("deepseek", "deepseek-reasoner")
|
||||
ai_client.reset_session()
|
||||
with patch("src.ai_client._load_credentials", return_value={"deepseek": {"api_key": "test-key"}}):
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.return_value = {
|
||||
"choices": [{"message": {"content": "OK"}, "finish_reason": "stop"}]
|
||||
}
|
||||
mock_post.return_value = mock_response
|
||||
|
||||
ai_client.send(md_content="Context", user_message="Message 1", base_dir=".")
|
||||
|
||||
args, kwargs = mock_post.call_args
|
||||
payload = kwargs["json"]
|
||||
|
||||
assert payload["model"] == "deepseek-reasoner"
|
||||
assert "tools" not in payload
|
||||
assert "temperature" not in payload
|
||||
assert "max_tokens" not in payload
|
||||
|
||||
@@ -19,11 +19,12 @@ def test_gui2_hubs_exist_in_show_windows(app_instance: App) -> None:
|
||||
def test_gui2_old_windows_removed_from_show_windows(app_instance: App) -> None:
|
||||
"""
|
||||
Verifies that the old fragmented windows are removed from show_windows.
|
||||
Note: Message, Response, and Tool Calls are kept as they are now optional standalone windows.
|
||||
"""
|
||||
old_windows = [
|
||||
"Projects", "Files", "Screenshots",
|
||||
"Provider", "System Prompts",
|
||||
"Message", "Response", "Tool Calls", "Comms History"
|
||||
"Comms History"
|
||||
]
|
||||
for old_win in old_windows:
|
||||
assert old_win not in app_instance.show_windows, f"Old window '{old_win}' should have been removed from show_windows"
|
||||
|
||||
@@ -77,7 +77,11 @@ def test_render_log_management_logic(app_instance: App) -> None:
|
||||
patch("src.gui_2.imgui.table_headers_row"), \
|
||||
patch("src.gui_2.imgui.table_next_row"), \
|
||||
patch("src.gui_2.imgui.table_next_column"), \
|
||||
patch("src.gui_2.imgui.same_line"), \
|
||||
patch("src.gui_2.imgui.text_colored"), \
|
||||
patch("src.gui_2.imgui.separator"), \
|
||||
patch("src.gui_2.imgui.button"):
|
||||
|
||||
mock_reg = MockRegistry.return_value
|
||||
mock_reg.data = {
|
||||
"session_1": {
|
||||
|
||||
@@ -39,11 +39,18 @@ def test_visual_mma_components(live_gui):
|
||||
client.push_event("mma_state_update", payload)
|
||||
print(" - MMA state update pushed.")
|
||||
|
||||
# Use ApiHookClient.wait_for_event if we had a specific event to wait for,
|
||||
# but here we just want to verify state.
|
||||
time.sleep(1) # Small sleep for UI to catch up with event queue
|
||||
# Poll for state update
|
||||
success = False
|
||||
for _ in range(50): # 10 seconds total
|
||||
if client.get_value("mma_active_tier") == "Tier 3":
|
||||
success = True
|
||||
break
|
||||
time.sleep(0.2)
|
||||
|
||||
assert success, f"State did not update to Tier 3. Current: {client.get_value('mma_active_tier')}"
|
||||
|
||||
# 3. Trigger HITL modal
|
||||
|
||||
print("Pushing 'mma_step_approval' event to trigger HITL modal...")
|
||||
approval_payload = {
|
||||
"ticket_id": "TICKET-002",
|
||||
|
||||
Reference in New Issue
Block a user