PYTHON
This commit is contained in:
@@ -10,7 +10,7 @@ from src import ai_client
|
||||
|
||||
def test_agent_capabilities_listing() -> None:
|
||||
# Mock credentials
|
||||
with patch("ai_client._load_credentials") as mock_creds:
|
||||
with patch("src.ai_client._load_credentials") as mock_creds:
|
||||
mock_creds.return_value = {"gemini": {"api_key": "fake-key"}}
|
||||
|
||||
# Mock the google-genai Client and models.list
|
||||
|
||||
@@ -36,8 +36,8 @@ def test_event_emission() -> None:
|
||||
|
||||
def test_send_emits_events_proper() -> None:
|
||||
ai_client.reset_session()
|
||||
with patch("ai_client._ensure_gemini_client"), \
|
||||
patch("ai_client._gemini_client") as mock_client:
|
||||
with patch("src.ai_client._ensure_gemini_client"), \
|
||||
patch("src.ai_client._gemini_client") as mock_client:
|
||||
mock_chat = MagicMock()
|
||||
mock_client.chats.create.return_value = mock_chat
|
||||
mock_response = MagicMock()
|
||||
@@ -57,9 +57,9 @@ def test_send_emits_events_proper() -> None:
|
||||
|
||||
def test_send_emits_tool_events() -> None:
|
||||
ai_client.reset_session() # Clear caches and chats to avoid test pollution
|
||||
with patch("ai_client._ensure_gemini_client"), \
|
||||
patch("ai_client._gemini_client") as mock_client, \
|
||||
patch("mcp_client.dispatch") as mock_dispatch:
|
||||
with patch("src.ai_client._ensure_gemini_client"), \
|
||||
patch("src.ai_client._gemini_client") as mock_client, \
|
||||
patch("src.mcp_client.dispatch") as mock_dispatch:
|
||||
mock_chat = MagicMock()
|
||||
mock_client.chats.create.return_value = mock_chat
|
||||
# 1. Setup mock response with a tool call
|
||||
|
||||
@@ -24,7 +24,7 @@ def test_telemetry_data_updates_correctly(app_instance: Any) -> None:
|
||||
"percentage": 75.0,
|
||||
}
|
||||
# 3. Patch the dependencies
|
||||
with patch('ai_client.get_token_stats', return_value=mock_stats) as mock_get_stats:
|
||||
with patch('src.ai_client.get_token_stats', return_value=mock_stats) as mock_get_stats:
|
||||
# 4. Call the method under test
|
||||
app_instance._refresh_api_metrics({}, md_content="test content")
|
||||
# 5. Assert the results
|
||||
@@ -41,7 +41,7 @@ def test_performance_history_updates(app_instance: Any) -> None:
|
||||
def test_gui_updates_on_event(app_instance: App) -> None:
|
||||
mock_stats = {"percentage": 50.0, "current": 500, "limit": 1000}
|
||||
app_instance.last_md = "mock_md"
|
||||
with patch('ai_client.get_token_stats', return_value=mock_stats):
|
||||
with patch('src.ai_client.get_token_stats', return_value=mock_stats):
|
||||
app_instance._on_api_event(payload={"text": "test"})
|
||||
app_instance._process_pending_gui_tasks()
|
||||
assert app_instance._token_stats["percentage"] == 50.0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import pytest
|
||||
import pytest
|
||||
from unittest.mock import MagicMock, patch
|
||||
from pathlib import Path
|
||||
|
||||
@@ -32,9 +32,9 @@ history = []
|
||||
|
||||
@pytest.fixture
|
||||
def app_instance(mock_config: Path, mock_project: Path, monkeypatch: pytest.MonkeyPatch) -> App:
|
||||
monkeypatch.setattr("gui_2.CONFIG_PATH", mock_config)
|
||||
with patch("project_manager.load_project") as mock_load, \
|
||||
patch("session_logger.open_session"):
|
||||
monkeypatch.setattr("src.models.CONFIG_PATH", mock_config)
|
||||
with patch("src.project_manager.load_project") as mock_load, \
|
||||
patch("src.session_logger.open_session"):
|
||||
mock_load.return_value = {
|
||||
"project": {"name": "test"},
|
||||
"discussion": {"roles": ["User", "AI"], "active": "main", "discussions": {"main": {"history": []}}},
|
||||
@@ -63,19 +63,19 @@ def test_render_log_management_logic(app_instance: App) -> None:
|
||||
app = app_instance
|
||||
app.show_windows["Log Management"] = True
|
||||
# Mock LogRegistry
|
||||
with patch("gui_2.LogRegistry") as MockRegistry, \
|
||||
patch("gui_2.imgui.begin") as mock_begin, \
|
||||
patch("gui_2.imgui.begin_table") as mock_begin_table, \
|
||||
patch("gui_2.imgui.text") as mock_text, \
|
||||
patch("gui_2.imgui.end_table"), \
|
||||
patch("gui_2.imgui.end"), \
|
||||
patch("gui_2.imgui.push_style_color"), \
|
||||
patch("gui_2.imgui.pop_style_color"), \
|
||||
patch("gui_2.imgui.table_setup_column"), \
|
||||
patch("gui_2.imgui.table_headers_row"), \
|
||||
patch("gui_2.imgui.table_next_row"), \
|
||||
patch("gui_2.imgui.table_next_column"), \
|
||||
patch("gui_2.imgui.button"):
|
||||
with patch("src.log_registry.LogRegistry") as MockRegistry, \
|
||||
patch("src.gui_2.imgui.begin") as mock_begin, \
|
||||
patch("src.gui_2.imgui.begin_table") as mock_begin_table, \
|
||||
patch("src.gui_2.imgui.text") as mock_text, \
|
||||
patch("src.gui_2.imgui.end_table"), \
|
||||
patch("src.gui_2.imgui.end"), \
|
||||
patch("src.gui_2.imgui.push_style_color"), \
|
||||
patch("src.gui_2.imgui.pop_style_color"), \
|
||||
patch("src.gui_2.imgui.table_setup_column"), \
|
||||
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.button"):
|
||||
mock_reg = MockRegistry.return_value
|
||||
mock_reg.data = {
|
||||
"session_1": {
|
||||
|
||||
@@ -4,7 +4,7 @@ from pathlib import Path
|
||||
from datetime import datetime, timedelta
|
||||
from src import session_logger
|
||||
from src.log_registry import LogRegistry
|
||||
from log_pruner import LogPruner
|
||||
from src.log_pruner import LogPruner
|
||||
|
||||
@pytest.fixture
|
||||
def e2e_setup(tmp_path: Path, monkeypatch: Any) -> Any:
|
||||
|
||||
@@ -11,7 +11,7 @@ from src import mcp_client
|
||||
def test_mcp_perf_tool_retrieval() -> None:
|
||||
mock_metrics = {"fps": 60, "last_frame_time_ms": 16.6}
|
||||
# Simulate tool call by patching the callback
|
||||
with patch('mcp_client.perf_monitor_callback', return_value=mock_metrics):
|
||||
with patch('src.mcp_client.perf_monitor_callback', return_value=mock_metrics):
|
||||
result = mcp_client.get_ui_performance()
|
||||
assert "60" in result
|
||||
assert "16.6" in result
|
||||
|
||||
@@ -70,7 +70,7 @@ class TestMMAApprovalIndicators:
|
||||
_pending_ask_dialog=False,
|
||||
)
|
||||
imgui_mock = _make_imgui_mock()
|
||||
with patch("gui_2.imgui", imgui_mock):
|
||||
with patch("src.gui_2.imgui", imgui_mock):
|
||||
App._render_mma_dashboard(app)
|
||||
combined = _collect_text_colored_args(imgui_mock)
|
||||
assert "APPROVAL PENDING" not in combined, (
|
||||
@@ -81,7 +81,7 @@ class TestMMAApprovalIndicators:
|
||||
"""'APPROVAL PENDING' badge must appear when _pending_mma_spawn is set."""
|
||||
app = _make_app(_pending_mma_spawn={"ticket_id": "T-001"})
|
||||
imgui_mock = _make_imgui_mock()
|
||||
with patch("gui_2.imgui", imgui_mock), patch("gui_2.math") as mock_math:
|
||||
with patch("src.gui_2.imgui", imgui_mock), patch("src.gui_2.math") as mock_math:
|
||||
mock_math.sin.return_value = 0.8
|
||||
App._render_mma_dashboard(app)
|
||||
combined = _collect_text_colored_args(imgui_mock)
|
||||
@@ -93,7 +93,7 @@ class TestMMAApprovalIndicators:
|
||||
"""'APPROVAL PENDING' badge must appear when _pending_mma_approval is set."""
|
||||
app = _make_app(_pending_mma_approval={"step": "test"})
|
||||
imgui_mock = _make_imgui_mock()
|
||||
with patch("gui_2.imgui", imgui_mock), patch("gui_2.math") as mock_math:
|
||||
with patch("src.gui_2.imgui", imgui_mock), patch("src.gui_2.math") as mock_math:
|
||||
mock_math.sin.return_value = 0.8
|
||||
App._render_mma_dashboard(app)
|
||||
combined = _collect_text_colored_args(imgui_mock)
|
||||
@@ -105,7 +105,7 @@ class TestMMAApprovalIndicators:
|
||||
"""'APPROVAL PENDING' badge must appear when _pending_ask_dialog is True."""
|
||||
app = _make_app(_pending_ask_dialog=True)
|
||||
imgui_mock = _make_imgui_mock()
|
||||
with patch("gui_2.imgui", imgui_mock), patch("gui_2.math") as mock_math:
|
||||
with patch("src.gui_2.imgui", imgui_mock), patch("src.gui_2.math") as mock_math:
|
||||
mock_math.sin.return_value = 0.8
|
||||
App._render_mma_dashboard(app)
|
||||
combined = _collect_text_colored_args(imgui_mock)
|
||||
|
||||
@@ -8,11 +8,11 @@ from src.gui_2 import App
|
||||
def app_instance() -> Any:
|
||||
with (
|
||||
patch("src.models.load_config", return_value={"ai": {}, "projects": {}}),
|
||||
patch("gui_2.save_config"),
|
||||
patch("gui_2.project_manager"),
|
||||
patch("app_controller.project_manager") as mock_pm,
|
||||
patch("gui_2.session_logger"),
|
||||
patch("gui_2.immapp.run"),
|
||||
patch("src.gui_2.save_config"),
|
||||
patch("src.gui_2.project_manager"),
|
||||
patch("src.app_controller.project_manager") as mock_pm,
|
||||
patch("src.gui_2.session_logger"),
|
||||
patch("src.gui_2.immapp.run"),
|
||||
patch("src.app_controller.AppController._load_active_project"),
|
||||
patch("src.app_controller.AppController._fetch_models"),
|
||||
patch.object(App, "_load_fonts"),
|
||||
|
||||
@@ -56,7 +56,7 @@ class TestMMADashboardStreams:
|
||||
app = _make_app(mma_streams={"Tier 1": "hello"})
|
||||
imgui_mock = _make_imgui_mock()
|
||||
imgui_mock.begin_child.return_value = True
|
||||
with patch("gui_2.imgui", imgui_mock):
|
||||
with patch("src.gui_2.imgui", imgui_mock):
|
||||
App._render_tier_stream_panel(app, "Tier 1", "Tier 1")
|
||||
text_wrapped_args = " ".join(str(c) for c in imgui_mock.text_wrapped.call_args_list)
|
||||
assert "hello" in text_wrapped_args, "text_wrapped not called with stream content 'hello'"
|
||||
@@ -69,7 +69,7 @@ class TestMMADashboardStreams:
|
||||
})
|
||||
imgui_mock = _make_imgui_mock()
|
||||
imgui_mock.begin_child.return_value = True
|
||||
with patch("gui_2.imgui", imgui_mock):
|
||||
with patch("src.gui_2.imgui", imgui_mock):
|
||||
App._render_tier_stream_panel(app, "Tier 3", None)
|
||||
text_args = " ".join(str(c) for c in imgui_mock.text.call_args_list)
|
||||
assert "T-001" in text_args, "imgui.text not called with 'T-001' worker sub-header"
|
||||
|
||||
@@ -7,8 +7,8 @@ from src import mma_prompts
|
||||
|
||||
class TestOrchestratorPM(unittest.TestCase):
|
||||
|
||||
@patch('summarize.build_summary_markdown')
|
||||
@patch('ai_client.send')
|
||||
@patch('src.summarize.build_summary_markdown')
|
||||
@patch('src.ai_client.send')
|
||||
def test_generate_tracks_success(self, mock_send: Any, mock_summarize: Any) -> None:
|
||||
# Setup mocks
|
||||
mock_summarize.return_value = "REPO_MAP_CONTENT"
|
||||
@@ -43,8 +43,8 @@ class TestOrchestratorPM(unittest.TestCase):
|
||||
# Verify result
|
||||
self.assertEqual(result[0]['id'], mock_response_data[0]['id'])
|
||||
|
||||
@patch('summarize.build_summary_markdown')
|
||||
@patch('ai_client.send')
|
||||
@patch('src.summarize.build_summary_markdown')
|
||||
@patch('src.ai_client.send')
|
||||
def test_generate_tracks_markdown_wrapped(self, mock_send: Any, mock_summarize: Any) -> None:
|
||||
mock_summarize.return_value = "REPO_MAP"
|
||||
mock_response_data = [{"id": "track_1"}]
|
||||
@@ -58,8 +58,8 @@ class TestOrchestratorPM(unittest.TestCase):
|
||||
result = orchestrator_pm.generate_tracks("req", {}, [])
|
||||
self.assertEqual(result, expected_result)
|
||||
|
||||
@patch('summarize.build_summary_markdown')
|
||||
@patch('ai_client.send')
|
||||
@patch('src.summarize.build_summary_markdown')
|
||||
@patch('src.ai_client.send')
|
||||
def test_generate_tracks_malformed_json(self, mock_send: Any, mock_summarize: Any) -> None:
|
||||
mock_summarize.return_value = "REPO_MAP"
|
||||
mock_send.return_value = "NOT A JSON"
|
||||
|
||||
@@ -28,7 +28,7 @@ class TestOrchestratorPMHistory(unittest.TestCase):
|
||||
with open(track_path / "spec.md", "w") as f:
|
||||
f.write(spec_content)
|
||||
|
||||
@patch('orchestrator_pm.CONDUCTOR_PATH', Path("test_conductor"))
|
||||
@patch('src.orchestrator_pm.CONDUCTOR_PATH', Path("test_conductor"))
|
||||
def test_get_track_history_summary(self) -> None:
|
||||
self.create_track(self.archive_dir, "track_001", "Initial Setup", "completed", "Setting up the project structure.")
|
||||
self.create_track(self.tracks_dir, "track_002", "Feature A", "in_progress", "Implementing Feature A.")
|
||||
@@ -40,7 +40,7 @@ class TestOrchestratorPMHistory(unittest.TestCase):
|
||||
self.assertIn("in_progress", summary)
|
||||
self.assertIn("Implementing Feature A.", summary)
|
||||
|
||||
@patch('orchestrator_pm.CONDUCTOR_PATH', Path("test_conductor"))
|
||||
@patch('src.orchestrator_pm.CONDUCTOR_PATH', Path("test_conductor"))
|
||||
def test_get_track_history_summary_missing_files(self) -> None:
|
||||
track_path = self.tracks_dir / "track_003"
|
||||
track_path.mkdir(exist_ok=True)
|
||||
@@ -51,8 +51,8 @@ class TestOrchestratorPMHistory(unittest.TestCase):
|
||||
self.assertIn("pending", summary)
|
||||
self.assertIn("No overview available", summary)
|
||||
|
||||
@patch('orchestrator_pm.summarize.build_summary_markdown')
|
||||
@patch('ai_client.send')
|
||||
@patch('src.orchestrator_pm.summarize.build_summary_markdown')
|
||||
@patch('src.ai_client.send')
|
||||
def test_generate_tracks_with_history(self, mock_send: MagicMock, mock_summarize: MagicMock) -> None:
|
||||
mock_summarize.return_value = "REPO_MAP"
|
||||
mock_send.return_value = "[]"
|
||||
|
||||
Reference in New Issue
Block a user