9e07fac1db
Per post_module_taxonomy_de_cruft_20260627 Phase 2 (FR7 continued).
The previous migration commit (8f11340b) handled the
'from src.models import X' pattern (85 sites). This commit handles
the 'models.<moved_class>' attribute access pattern (44 sites in 20
files), which the __getattr__ shim previously supported.
The migration was performed by the one-time script
scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/migrate_models_attr.py
which:
1. For each 'models.<moved_class>' reference, replaces it with the
bare class name (e.g., 'models.MCPConfiguration' -> 'MCPConfiguration')
2. Adds the import 'from src.<destination> import <moved_class>' at
the top of the file (deduplicated if the import already exists)
3. Skips moved classes that the file already imports directly
The migration script inserts the import after the 'from __future__
import annotations' line if present; otherwise it adds the import
to the destination module's existing import block. Two files
required manual fixes because the script's regex didn't handle them:
- src/rag_engine.py: uses 'from src import models' (not 'from
src.models import X'); the class is accessed
via 'models.RAGConfig'. Replaced with a
direct 'from src.mcp_client import RAGConfig'
import and removed the 'from src import models'.
- tests/test_project_context_20260627.py: uses the parens-style
multi-line 'from src.models import (X, Y, Z)'.
Replaced with the parens-style direct import.
After this commit:
- 'models.MCPConfiguration', 'models.FileItem', 'models.Ticket', etc.
no longer work in src/ and tests/ (the AttributeError raises
because models.py no longer has the __getattr__ entries for
moved classes)
- All consumer files have direct imports of the moved classes
Total: 44 'models.<moved_class>' references rewritten across 20 files.
89 lines
3.8 KiB
Python
89 lines
3.8 KiB
Python
import pytest
|
|
from unittest.mock import MagicMock, patch
|
|
from src import gui_2
|
|
from src.gui_2 import App, C_LBL, C_VAL
|
|
from src.mma import Ticket
|
|
|
|
def test_render_mma_dashboard_progress():
|
|
# Create a mock for the imgui module used in gui_2
|
|
mock_imgui = MagicMock()
|
|
|
|
# Configure ImVec4 and ImVec2
|
|
mock_imgui.ImVec2 = MagicMock(side_effect=lambda x, y: (float(x), float(y)))
|
|
mock_imgui.ImVec4 = MagicMock(side_effect=lambda r, g, b, a: (float(r), float(g), float(b), float(a)))
|
|
|
|
# Configure calls that return tuples
|
|
mock_imgui.input_text_multiline.return_value = (False, "")
|
|
mock_imgui.input_text.return_value = (False, "")
|
|
mock_imgui.checkbox.return_value = (False, False)
|
|
mock_imgui.begin_combo.return_value = (False, "")
|
|
mock_imgui.selectable.return_value = (False, False)
|
|
mock_imgui.begin_table.return_value = True
|
|
mock_imgui.begin_tab_item.return_value = (True, True)
|
|
mock_imgui.collapsing_header.return_value = False
|
|
# Patch where it is actually used
|
|
with patch('src.gui_2.imgui', mock_imgui), \
|
|
patch('src.imgui_scopes.imgui', new=mock_imgui), \
|
|
patch('src.theme_2.imgui', new=mock_imgui), \
|
|
patch('src.gui_2.cost_tracker.estimate_cost', return_value=0.0):
|
|
|
|
# Mock App instance - no spec because of delegation
|
|
app = MagicMock()
|
|
|
|
# Setup mock state
|
|
app.active_track = MagicMock()
|
|
app.active_track.description = "Test Track"
|
|
|
|
# Mock self.active_track.tickets as a list of src.Ticket objects
|
|
app.active_track.tickets = [
|
|
Ticket(id='T1', description='desc', status='completed'),
|
|
Ticket(id='T2', description='desc', status='in_progress'),
|
|
Ticket(id='T3', description='desc', status='blocked'),
|
|
Ticket(id='T4', description='desc', status='todo')
|
|
]
|
|
|
|
app.is_viewing_prior_session = False
|
|
app.perf_profiling_enabled = False
|
|
app.mma_tier_usage = {}
|
|
app.mma_status = "idle"
|
|
app.active_tier = None
|
|
app._pending_mma_spawn = None
|
|
app._pending_mma_approval = None
|
|
app._pending_ask_dialog = False
|
|
app.tracks = []
|
|
app.ui_epic_input = ""
|
|
app.ui_conductor_setup_summary = ""
|
|
app.ui_new_track_name = ""
|
|
app.ui_new_track_desc = ""
|
|
app.ui_new_track_type = "feature"
|
|
app.mma_step_mode = False
|
|
app.node_editor_ctx = None
|
|
app._avg_ticket_time = 60
|
|
|
|
# Call the method
|
|
# Dashboard now delegates to sub-methods, so we wire them up to execute their real logic on the mock instance.
|
|
app._render_mma_focus_selector.side_effect = lambda: gui_2.render_mma_focus_selector(app)
|
|
app._render_mma_track_summary.side_effect = lambda: gui_2.render_mma_track_summary(app)
|
|
app._render_mma_epic_planner.side_effect = lambda: gui_2.render_mma_epic_planner(app)
|
|
app._render_mma_conductor_setup.side_effect = lambda: gui_2.render_mma_conductor_setup(app)
|
|
app._render_mma_track_browser.side_effect = lambda: gui_2.render_mma_track_browser(app)
|
|
app._render_mma_global_controls.side_effect = lambda: gui_2.render_mma_global_controls(app)
|
|
app._render_mma_usage_section.side_effect = lambda: gui_2.render_mma_usage_section(app)
|
|
app._render_mma_agent_streams.side_effect = lambda: gui_2.render_mma_agent_streams(app)
|
|
|
|
gui_2.render_mma_dashboard(app)
|
|
# Assertions
|
|
# 1 completed out of 4 tickets = 25.0% progress
|
|
# Update assertions: imgui.progress_bar is called with (0.25, (-1.0, 0.0), '25.0%')
|
|
mock_imgui.progress_bar.assert_any_call(0.25, (-1.0, 0.0), "25.0%")
|
|
|
|
# Verify status breakdown counts are asserted via imgui.text_colored calls
|
|
mock_imgui.text_colored.assert_any_call(C_LBL(), "Completed:")
|
|
mock_imgui.text_colored.assert_any_call(C_VAL(), "1")
|
|
mock_imgui.text_colored.assert_any_call(C_LBL(), "In Progress:")
|
|
mock_imgui.text_colored.assert_any_call(C_VAL(), "1")
|
|
mock_imgui.text_colored.assert_any_call(C_LBL(), "Blocked:")
|
|
mock_imgui.text_colored.assert_any_call(C_VAL(), "1")
|
|
mock_imgui.text_colored.assert_any_call(C_LBL(), "Todo:")
|
|
mock_imgui.text_colored.assert_any_call(C_VAL(), "1")
|