Private
Public Access
0
0

gemini quota exhausted: fixing regressions in test suite

This commit is contained in:
2026-05-16 14:45:06 -04:00
parent 49082e5036
commit bf5b426c24
17 changed files with 223 additions and 152 deletions
@@ -0,0 +1,53 @@
# Plan: Fix Test Suite Regressions
## Objective
Restore the full test suite to a passing state after the `gui_2.py` refactoring (Phase 2 & Phase 3 of Context Composition Redesign).
## Key Files & Context
- `src/gui_2.py`: The main GUI entry point where methods were moved to module level.
- `src/hot_reloader.py`: Handles module registration, currently causing collisions in tests.
- `tests/*.py`: Multiple test files referencing deleted/moved methods.
## Implementation Steps
### Phase 1: Fix HotReloader Collisions
- [ ] Modify `src/gui_2.py` to check if `src.gui_2` is already registered before calling `HotReloader.register`. This allows multiple `App()` instances (common in tests) without triggering `ValueError`.
- [ ] Revert `src/hot_reloader.py` to its original state (raising `ValueError` on duplicate registration) to satisfy existing tests for that logic.
### Phase 2: Fix Method Migration Regressions (Batch)
- [ ] Identify all test files calling `app._render_*` or checking `hasattr(App, '_render_*')`.
- [ ] Use Tier 3 workers to surgically update these tests:
- Change `app._render_XYZ()` to `gui_2.render_XYZ(app)`.
- Change `hasattr(App, '_render_XYZ')` to `hasattr(gui_2, 'render_XYZ')` (and import `gui_2`).
- Note: Some internal helpers might still be prefixed with `_` at the module level.
- [ ] Target the following specific files:
- `tests/test_ast_inspector_extended.py`
- `tests/test_discussion_takes_gui.py`
- `tests/test_gui_discussion_tabs.py`
- `tests/test_gui_fast_render.py`
- `tests/test_gui_phase4.py`
- `tests/test_gui_progress.py`
- `tests/test_gui_symbol_navigation.py`
- `tests/test_gui_synthesis.py`
- `tests/test_log_management_ui.py`
- `tests/test_mma_approval_indicators.py`
- `tests/test_mma_dashboard_streams.py`
- `tests/test_project_settings_rename.py`
- `tests/test_rag_gui_presence.py`
- `tests/test_selectable_ui.py`
- `tests/test_session_hub_merge.py`
- `tests/test_shader_live_editor.py`
- `tests/test_takes_panel.py`
- `tests/test_thinking_gui.py`
- `tests/test_token_viz.py`
- `tests/test_ui_summary_only_removal.py`
### Phase 3: Address Specific Logic Failures
- [ ] `tests/test_py_struct_tools.py`: Investigate and fix why definitions are not found.
- [ ] `tests/test_rag_phase4_final_verify.py`: Investigate why RAG context is missing in history.
- [ ] `tests/test_rag_phase4_stress.py`: Investigate timing issues (incremental indexing duration).
- [ ] `tests/test_gui_kill_button.py`: Investigate missing "Actions" column in ticket queue.
## Verification & Testing
- [ ] Run the full test suite using the batch script: `uv run python scripts/run_tests_batched.py`.
- [ ] Ensure all 243 test files pass.
+7 -6
View File
@@ -119,12 +119,13 @@ class App:
# --- Initialization ---
self.controller.init_state()
from src.hot_reloader import HotReloader, HotModule
HotReloader.register(HotModule(
name='src.gui_2',
file_path=__file__,
state_keys=['active_discussion', 'show_windows', 'ui_file_paths', 'ui_screenshot_paths', 'disc_entries', 'disc_roles'],
delegation_targets=['_render_main_interface', '_render_discussion_hub', '_render_files_and_media', '_render_ai_settings_hub', '_render_operations_hub', '_render_mma_dashboard']
))
if 'src.gui_2' not in HotReloader.HOT_MODULES:
HotReloader.register(HotModule(
name='src.gui_2',
file_path=__file__,
state_keys=['active_discussion', 'show_windows', 'ui_file_paths', 'ui_screenshot_paths', 'disc_entries', 'disc_roles'],
delegation_targets=['_render_main_interface', '_render_discussion_hub', '_render_files_and_media', '_render_ai_settings_hub', '_render_operations_hub', '_render_mma_dashboard']
))
self.workspace_manager = workspace_manager.WorkspaceManager(project_root=self.controller.active_project_root)
self.disc_entries = self.controller.disc_entries
self.disc_roles = self.controller.disc_roles
+2
View File
@@ -18,6 +18,8 @@ class HotReloader:
@classmethod
def register(cls, module: HotModule) -> None:
if module.name in cls.HOT_MODULES:
raise ValueError(f"Module {module.name} already registered")
cls.HOT_MODULES[module.name] = module
@classmethod
+2 -2
View File
@@ -1,6 +1,6 @@
import unittest.mock
from unittest.mock import MagicMock, patch
from src.gui_2 import App
from src.gui_2 import App, render_ast_inspector_modal
from src import models
def test_ast_inspector_line_range_parsing():
@@ -37,7 +37,7 @@ def test_ast_inspector_line_range_parsing():
mock_imscope.style_var.return_value.__enter__.return_value = None
# 4. Call the method
App._render_ast_inspector_modal(app)
render_ast_inspector_modal(app)
# 5. Assertions
assert len(app._cached_ast_nodes) == 2
+51 -50
View File
@@ -1,5 +1,6 @@
import pytest
from unittest.mock import MagicMock, patch, call
from src import gui_2
from src.gui_2 import App
@pytest.fixture
@@ -40,66 +41,66 @@ def app_instance():
def test_render_discussion_tabs(app_instance):
"""Verify that _render_discussion_panel uses tabs for discussions."""
with patch('src.gui_2.imgui') as mock_imgui, \
patch('src.gui_2.imscope') as mock_imscope:
mock_imgui.collapsing_header.return_value = True
mock_imgui.begin_combo.return_value = False
mock_imgui.input_text.return_value = (False, "")
mock_imgui.input_int.return_value = (False, 0)
mock_imgui.input_text_multiline.return_value = (False, "")
mock_imgui.button.return_value = False
mock_imgui.checkbox.return_value = (False, False)
mock_imgui.begin_child.return_value = True
mock_imgui.selectable.return_value = (False, False)
mock_imgui.ListClipper.return_value.step.return_value = False
mock_imgui.begin_tab_bar.return_value = True
patch('src.gui_2.imscope') as mock_imscope:
mock_imgui.collapsing_header.return_value = True
mock_imgui.begin_combo.return_value = False
mock_imgui.input_text.return_value = (False, "")
mock_imgui.input_int.return_value = (False, 0)
mock_imgui.input_text_multiline.return_value = (False, "")
mock_imgui.button.return_value = False
mock_imgui.checkbox.return_value = (False, False)
mock_imgui.begin_child.return_value = True
mock_imgui.selectable.return_value = (False, False)
mock_imgui.ListClipper.return_value.step.return_value = False
mock_imgui.begin_tab_bar.return_value = True
mock_imscope.window.return_value.__enter__.return_value = (True, True)
mock_imscope.child.return_value.__enter__.return_value = True
mock_imscope.table.return_value.__enter__.return_value = True
mock_imscope.tree_node_ex.return_value.__enter__.return_value = True
mock_imscope.tab_item.return_value.__enter__.return_value = (True, True)
mock_imscope.style_color.return_value.__enter__.return_value = None
mock_imscope.style_var.return_value.__enter__.return_value = None
mock_imscope.window.return_value.__enter__.return_value = (True, True)
mock_imscope.child.return_value.__enter__.return_value = True
mock_imscope.table.return_value.__enter__.return_value = True
mock_imscope.tree_node_ex.return_value.__enter__.return_value = True
mock_imscope.tab_item.return_value.__enter__.return_value = (True, True)
mock_imscope.style_color.return_value.__enter__.return_value = None
mock_imscope.style_var.return_value.__enter__.return_value = None
mock_imgui.begin_tab_item.return_value = (True, True)
mock_imgui.begin_tab_item.return_value = (True, True)
app_instance._render_discussion_panel()
gui_2.render_discussion_panel(app_instance)
mock_imgui.begin_tab_bar.assert_called_with("discussion_takes_tabs")
assert mock_imscope.tab_item.call_count >= 3, f"Expected at least 3 tab items via imscope.tab_item, got {mock_imscope.tab_item.call_count}"
mock_imgui.begin_tab_bar.assert_called_with("discussion_takes_tabs")
assert mock_imscope.tab_item.call_count >= 3, f"Expected at least 3 tab items via imscope.tab_item, got {mock_imscope.tab_item.call_count}"
def test_switching_discussion_via_tabs(app_instance):
"""Verify that clicking a tab switches the discussion."""
with patch('src.gui_2.imgui') as mock_imgui, \
patch('src.gui_2.imscope') as mock_imscope, \
patch('src.app_controller.AppController._switch_discussion') as mock_switch:
mock_imgui.collapsing_header.return_value = True
mock_imgui.begin_combo.return_value = False
mock_imgui.input_text.return_value = (False, "")
mock_imgui.input_int.return_value = (False, 0)
mock_imgui.input_text_multiline.return_value = (False, "")
mock_imgui.button.return_value = False
mock_imgui.checkbox.return_value = (False, False)
mock_imgui.begin_child.return_value = True
mock_imgui.selectable.return_value = (False, False)
mock_imgui.ListClipper.return_value.step.return_value = False
mock_imgui.begin_tab_bar.return_value = True
patch('src.gui_2.imscope') as mock_imscope, \
patch('src.app_controller.AppController._switch_discussion') as mock_switch:
mock_imgui.collapsing_header.return_value = True
mock_imgui.begin_combo.return_value = False
mock_imgui.input_text.return_value = (False, "")
mock_imgui.input_int.return_value = (False, 0)
mock_imgui.input_text_multiline.return_value = (False, "")
mock_imgui.button.return_value = False
mock_imgui.checkbox.return_value = (False, False)
mock_imgui.begin_child.return_value = True
mock_imgui.selectable.return_value = (False, False)
mock_imgui.ListClipper.return_value.step.return_value = False
mock_imgui.begin_tab_bar.return_value = True
mock_imscope.window.return_value.__enter__.return_value = (True, True)
mock_imscope.child.return_value.__enter__.return_value = True
mock_imscope.table.return_value.__enter__.return_value = True
mock_imscope.tree_node_ex.return_value.__enter__.return_value = True
mock_imscope.tab_item.return_value.__enter__.return_value = (True, True)
mock_imscope.style_color.return_value.__enter__.return_value = None
mock_imscope.style_var.return_value.__enter__.return_value = None
mock_imscope.window.return_value.__enter__.return_value = (True, True)
mock_imscope.child.return_value.__enter__.return_value = True
mock_imscope.table.return_value.__enter__.return_value = True
mock_imscope.tree_node_ex.return_value.__enter__.return_value = True
mock_imscope.tab_item.return_value.__enter__.return_value = (True, True)
mock_imscope.style_color.return_value.__enter__.return_value = None
mock_imscope.style_var.return_value.__enter__.return_value = None
def begin_tab_item_side_effect(label, p_open=None, flags=None):
if "main_take_1" in label:
return (True, True)
return (False, True)
def begin_tab_item_side_effect(label, p_open=None, flags=None):
if "main_take_1" in label:
return (True, True)
return (False, True)
mock_imgui.begin_tab_item.side_effect = begin_tab_item_side_effect
mock_imgui.begin_tab_item.side_effect = begin_tab_item_side_effect
app_instance._render_discussion_panel()
gui_2.render_discussion_panel(app_instance)
assert mock_switch.called, f"Expected _switch_discussion to be called"
assert mock_switch.called, f"Expected _switch_discussion to be called"
+7 -8
View File
@@ -1,6 +1,5 @@
import pytest
from unittest.mock import patch, MagicMock, PropertyMock
from src import gui_2
@pytest.fixture
@@ -27,7 +26,7 @@ def test_discussion_tabs_rendered(mock_gui):
patch('src.gui_2.imscope') as mock_imscope, \
patch('src.imgui_scopes.imgui', new=mock_imgui), \
patch('src.app_controller.AppController.active_project_root', new_callable=PropertyMock, return_value='.'):
# Setup imscope mocks
mock_imscope.window.return_value.__enter__.return_value = (True, True)
mock_imscope.child.return_value.__enter__.return_value = True
@@ -40,7 +39,7 @@ def test_discussion_tabs_rendered(mock_gui):
# We expect a combo box for base discussion
mock_imgui.begin_combo.return_value = True
mock_imgui.selectable.return_value = (False, False)
# We expect a tab bar for takes
mock_imgui.begin_tab_bar.return_value = True
mock_imgui.begin_tab_item.return_value = (True, True)
@@ -48,16 +47,16 @@ def test_discussion_tabs_rendered(mock_gui):
mock_imgui.input_text_multiline.return_value = (False, "")
mock_imgui.checkbox.return_value = (False, False)
mock_imgui.input_int.return_value = (False, 0)
mock_clipper = MagicMock()
mock_clipper.step.return_value = False
mock_imgui.ListClipper.return_value = mock_clipper
mock_gui._render_discussion_panel()
gui_2.render_discussion_panel(mock_gui)
mock_imgui.begin_combo.assert_called_once_with("##disc_sel", 'main')
mock_imgui.begin_tab_bar.assert_called_once_with('discussion_takes_tabs')
calls = [c[0][0] for c in mock_imscope.tab_item.call_args_list]
assert 'Original###main' in calls
assert 'Take 1###main_take_1' in calls
+12 -6
View File
@@ -1,6 +1,7 @@
import pytest
from unittest.mock import patch, MagicMock
from src.gui_2 import App
from src import gui_2
def test_render_context_composition_panel_fast(app_instance: App):
"""Verifies that the context composition panel rendering path executes without exceptions."""
@@ -18,9 +19,9 @@ def test_render_context_composition_panel_fast(app_instance: App):
mock_imscope.tab_item.return_value.__enter__.return_value = (True, True)
try:
app_instance._render_context_composition_panel()
gui_2.render_context_composition_panel(app_instance)
except Exception as e:
pytest.fail(f"_render_context_composition_panel raised an exception: {e}")
pytest.fail(f"render_context_composition_panel raised an exception: {e}")
def test_render_discussion_panel_fast(app_instance: App):
"""Verifies that the discussion panel rendering path executes without exceptions."""
@@ -37,10 +38,15 @@ def test_render_discussion_panel_fast(app_instance: App):
mock_imgui.ListClipper.return_value.step.return_value = False
mock_imscope.tab_item.return_value.__enter__.return_value = (True, True)
# Mocks for complex imgui logic in render_discussion_tab
mock_imgui.is_item_active.return_value = False
mock_imgui.begin_tab_bar.return_value = False
mock_imgui.begin_tab_item.return_value = (False, False)
try:
app_instance._render_discussion_panel()
gui_2.render_discussion_hub(app_instance)
except Exception as e:
pytest.fail(f"_render_discussion_panel raised an exception: {e}")
pytest.fail(f"render_discussion_hub raised an exception: {e}")
def test_render_files_and_media_fast(app_instance: App):
"""Verifies that the files and media panel rendering path executes without exceptions."""
@@ -58,6 +64,6 @@ def test_render_files_and_media_fast(app_instance: App):
mock_imscope.tab_item.return_value.__enter__.return_value = (True, True)
try:
app_instance._render_files_and_media()
gui_2.render_files_and_media(app_instance)
except Exception as e:
pytest.fail(f"_render_files_and_media raised an exception: {e}")
pytest.fail(f"render_files_and_media raised an exception: {e}")
+14 -3
View File
@@ -1,5 +1,6 @@
import pytest
from unittest.mock import MagicMock, patch
from src import gui_2
from src.gui_2 import App
from src.models import Track
@@ -70,6 +71,8 @@ def test_delete_ticket_logic(mock_app: App):
def test_track_discussion_toggle(mock_app: App):
with (
patch('src.gui_2.imgui') as mock_imgui,
patch('src.theme_2.imgui', new=mock_imgui),
patch('src.imgui_scopes.imgui', new=mock_imgui),
patch('src.gui_2.imscope') as mock_imscope,
patch('src.gui_2.project_manager.load_track_history', return_value=["@2026-03-01 12:00:00\n[User]\nTrack Hello"]) as mock_load,
patch('src.gui_2.project_manager.str_to_entry', side_effect=lambda s, roles: {"ts": "12:00", "role": "User", "content": s.split("\n")[-1]}),
@@ -97,11 +100,19 @@ def test_track_discussion_toggle(mock_app: App):
mock_imgui.begin_combo.return_value = False
mock_imgui.selectable.return_value = (False, False)
mock_imgui.button.return_value = False
mock_imgui.collapsing_header.return_value = True # For Discussions header
mock_imgui.combo.return_value = (False, 0)
mock_imgui.begin_tab_bar.return_value = True
mock_imgui.collapsing_header.return_value = True # For Discussions header
mock_imgui.input_text.side_effect = lambda label, value, *args, **kwargs: (False, value)
mock_imgui.input_text_multiline.side_effect = lambda label, value, *args, **kwargs: (False, value)
mock_imgui.input_int.side_effect = lambda label, value, *args, **kwargs: (False, value)
mock_imgui.begin_child.return_value = True
mock_imgui.get_window_height.return_value = 800.0
mock_imgui.get_io.return_value.mouse_delta.y = 0.0
mock_imgui.is_item_active.return_value = False
mock_imgui.get_style.return_value.color_.return_value = (1, 1, 1, 1)
mock_imgui.Col_ = MagicMock()
mock_imgui.set_scroll_here_y.return_value = None
# Mock clipper to avoid the while loop hang
mock_clipper = MagicMock()
mock_clipper.step.side_effect = [True, False]
@@ -109,7 +120,7 @@ def test_track_discussion_toggle(mock_app: App):
mock_clipper.display_end = 0
mock_imgui.ListClipper.return_value = mock_clipper
mock_app._render_discussion_panel()
gui_2.render_discussion_hub(mock_app)
assert mock_app._track_discussion_active
mock_flush.assert_called()
@@ -127,7 +138,7 @@ def test_track_discussion_toggle(mock_app: App):
mock_imgui.checkbox.side_effect = checkbox_off_side_effect
mock_clipper.step.side_effect = [True, False] # Reset clipper
mock_app._render_discussion_panel()
gui_2.render_discussion_hub(mock_app)
assert not mock_app._track_discussion_active
mock_switch.assert_called_with(mock_app.active_discussion)
+10 -9
View File
@@ -1,5 +1,6 @@
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.models import Ticket
@@ -60,16 +61,16 @@ def test_render_mma_dashboard_progress():
# 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: App._render_mma_focus_selector(app)
app._render_mma_track_summary.side_effect = lambda: App._render_mma_track_summary(app)
app._render_mma_epic_planner.side_effect = lambda: App._render_mma_epic_planner(app)
app._render_mma_conductor_setup.side_effect = lambda: App._render_mma_conductor_setup(app)
app._render_mma_track_browser.side_effect = lambda: App._render_mma_track_browser(app)
app._render_mma_global_controls.side_effect = lambda: App._render_mma_global_controls(app)
app._render_mma_usage_section.side_effect = lambda: App._render_mma_usage_section(app)
app._render_mma_agent_streams.side_effect = lambda: App._render_mma_agent_streams(app)
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)
App._render_mma_dashboard(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%')
+2 -1
View File
@@ -1,5 +1,6 @@
import pytest
from unittest.mock import MagicMock, patch
from src import gui_2
from src.gui_2 import App
@pytest.mark.parametrize("role", ["User", "AI"])
@@ -75,7 +76,7 @@ def test_render_discussion_panel_symbol_lookup(mock_app, role):
mock_mcp.read_file.return_value = "class MyClass:\n pass"
# Execute the panel rendering
mock_app._render_discussion_panel()
gui_2.render_discussion_panel(mock_app)
# Assertions
# 1. Assert that the regex correctly identifies the pattern and imgui.button('[Source]##0_0') is called
+3 -2
View File
@@ -1,5 +1,6 @@
import pytest
from unittest.mock import MagicMock, patch, ANY
from src import gui_2
from src.gui_2 import App
@pytest.fixture
@@ -35,7 +36,7 @@ def app_instance():
yield app
def test_render_synthesis_panel(app_instance):
"""Verify that _render_synthesis_panel renders checkboxes for takes and input for prompt."""
"""Verify that render_synthesis_panel renders checkboxes for takes and input for prompt."""
with patch('src.gui_2.imgui') as mock_imgui, \
patch('src.gui_2.imscope') as mock_imscope:
mock_imgui.checkbox.return_value = (False, False)
@@ -52,7 +53,7 @@ def test_render_synthesis_panel(app_instance):
mock_imscope.style_var.return_value.__enter__.return_value = None
# Call the method we are testing
app_instance._render_synthesis_panel()
gui_2.render_synthesis_panel(app_instance)
# 1. Assert imgui.checkbox is called for each take in project_dict['discussion']['discussions']
discussions = app_instance.project['discussion']['discussions']
+4 -5
View File
@@ -1,8 +1,7 @@
import pytest
from unittest.mock import MagicMock, patch
from pathlib import Path
# We can safely import gui_2 if we don't instantiate App without mocking its threads
from src import gui_2
from src.gui_2 import App
@pytest.fixture
@@ -60,8 +59,8 @@ def test_log_management_init(app_instance: App) -> None:
app = app_instance
assert "Log Management" in app.show_windows
assert app.show_windows["Log Management"] is False
assert hasattr(app, "_render_log_management")
assert callable(app._render_log_management)
assert hasattr(gui_2, "render_log_management")
assert callable(gui_2.render_log_management)
def test_render_log_management_logic(app_instance: App) -> None:
app = app_instance
@@ -98,7 +97,7 @@ def test_render_log_management_logic(app_instance: App) -> None:
mock_imscope.window.return_value = mock_window_cm
mock_begin_table.return_value = True
app._render_log_management()
gui_2.render_log_management(app)
mock_imscope.window.assert_called_with("Log Management", app.show_windows["Log Management"])
mock_begin_table.assert_called()
mock_text.assert_any_call("session_1")
+16 -15
View File
@@ -1,6 +1,7 @@
from __future__ import annotations
from unittest.mock import patch, MagicMock
from src import gui_2
from src.gui_2 import App
@@ -63,18 +64,18 @@ def _make_app(**kwargs):
app.controller = mock_controller
# Ensure real methods are called for the dashboard rendering components
app._render_mma_dashboard = lambda: App._render_mma_dashboard(app)
app._render_mma_focus_selector = lambda: App._render_mma_focus_selector(app)
app._render_mma_track_summary = lambda: App._render_mma_track_summary(app)
app._render_mma_epic_planner = lambda: App._render_mma_epic_planner(app)
app._render_mma_conductor_setup = lambda: App._render_mma_conductor_setup(app)
app._render_mma_track_browser = lambda: App._render_mma_track_browser(app)
app._render_mma_global_controls = lambda: App._render_mma_global_controls(app)
app._render_mma_usage_section = lambda: App._render_mma_usage_section(app)
app._render_ticket_queue = lambda: App._render_ticket_queue(app)
app._render_mma_dashboard = lambda: gui_2.render_mma_dashboard(app)
app._render_mma_focus_selector = lambda: gui_2.render_mma_focus_selector(app)
app._render_mma_track_summary = lambda: gui_2.render_mma_track_summary(app)
app._render_mma_epic_planner = lambda: gui_2.render_mma_epic_planner(app)
app._render_mma_conductor_setup = lambda: gui_2.render_mma_conductor_setup(app)
app._render_mma_track_browser = lambda: gui_2.render_mma_track_browser(app)
app._render_mma_global_controls = lambda: gui_2.render_mma_global_controls(app)
app._render_mma_usage_section = lambda: gui_2.render_mma_usage_section(app)
app._render_ticket_queue = lambda: gui_2.render_ticket_queue(app)
app._render_window_if_open = lambda name, func, condition=True: func() if condition else None
app._render_mma_ticket_editor = lambda: App._render_mma_ticket_editor(app)
app._render_mma_agent_streams = lambda: App._render_mma_agent_streams(app)
app._render_mma_ticket_editor = lambda: gui_2.render_mma_ticket_editor(app)
app._render_mma_agent_streams = lambda: gui_2.render_mma_agent_streams(app)
return app
@@ -126,7 +127,7 @@ class TestMMAApprovalIndicators:
mock_imscope.style_color.return_value.__enter__.return_value = None
mock_imscope.style_var.return_value.__enter__.return_value = None
App._render_mma_dashboard(app)
gui_2.render_mma_dashboard(app)
combined = _collect_text_colored_args(imgui_mock)
assert "APPROVAL PENDING" not in combined, (
"text_colored called with 'APPROVAL PENDING' when no approval is pending"
@@ -147,7 +148,7 @@ class TestMMAApprovalIndicators:
mock_imscope.style_var.return_value.__enter__.return_value = None
mock_math.sin.return_value = 0.8
App._render_mma_dashboard(app)
gui_2.render_mma_dashboard(app)
combined = _collect_text_colored_args(imgui_mock)
assert "APPROVAL PENDING" in combined, (
"text_colored not called with 'APPROVAL PENDING' when _pending_mma_spawn is set"
@@ -168,7 +169,7 @@ class TestMMAApprovalIndicators:
mock_imscope.style_var.return_value.__enter__.return_value = None
mock_math.sin.return_value = 0.8
App._render_mma_dashboard(app)
gui_2.render_mma_dashboard(app)
combined = _collect_text_colored_args(imgui_mock)
assert "APPROVAL PENDING" in combined, (
"text_colored not called with 'APPROVAL PENDING' when _pending_mma_approval is set"
@@ -189,7 +190,7 @@ class TestMMAApprovalIndicators:
mock_imscope.style_var.return_value.__enter__.return_value = None
mock_math.sin.return_value = 0.8
App._render_mma_dashboard(app)
gui_2.render_mma_dashboard(app)
combined = _collect_text_colored_args(imgui_mock)
assert "APPROVAL PENDING" in combined, (
"text_colored not called with 'APPROVAL PENDING' when _pending_ask_dialog is True"
+10 -5
View File
@@ -1,6 +1,7 @@
from __future__ import annotations
from unittest.mock import patch, MagicMock
from src import gui_2
from src.gui_2 import App
@@ -64,7 +65,9 @@ class TestMMADashboardStreams:
app = _make_app(mma_streams={"Tier 1": "hello"})
imgui_mock = _make_imgui_mock()
imgui_mock.begin_child.return_value = True
with patch("src.gui_2.imgui", imgui_mock), patch("src.gui_2.imscope") as mock_imscope:
with patch("src.gui_2.imgui", imgui_mock), \
patch("src.gui_2.imscope") as mock_imscope, \
patch("src.gui_2.render_selectable_label") as mock_render:
# Setup imscope mocks
mock_imscope.window.return_value.__enter__.return_value = (True, True)
mock_imscope.child.return_value.__enter__.return_value = True
@@ -74,9 +77,9 @@ class TestMMADashboardStreams:
mock_imscope.style_color.return_value.__enter__.return_value = None
mock_imscope.style_var.return_value.__enter__.return_value = None
App._render_tier_stream_panel(app, "Tier 1", "Tier 1")
gui_2.render_tier_stream_panel(app, "Tier 1", "Tier 1")
app._render_selectable_label.assert_called_with('stream_Tier 1', 'hello', width=-1, multiline=True, height=0)
mock_render.assert_called_with(app, 'stream_Tier 1', 'hello', width=-1, multiline=True, height=0)
def test_tier3_renders_worker_subheaders(self):
"""_render_tier_stream_panel for Tier 3 must render a sub-header for each worker stream key."""
@@ -86,7 +89,9 @@ class TestMMADashboardStreams:
})
imgui_mock = _make_imgui_mock()
imgui_mock.begin_child.return_value = True
with patch("src.gui_2.imgui", imgui_mock), patch("src.gui_2.imscope") as mock_imscope:
with patch("src.gui_2.imgui", imgui_mock), \
patch("src.gui_2.imscope") as mock_imscope, \
patch("src.gui_2.render_selectable_label"):
# Setup imscope mocks
mock_imscope.window.return_value.__enter__.return_value = (True, True)
mock_imscope.child.return_value.__enter__.return_value = True
@@ -96,7 +101,7 @@ class TestMMADashboardStreams:
mock_imscope.style_color.return_value.__enter__.return_value = None
mock_imscope.style_var.return_value.__enter__.return_value = None
App._render_tier_stream_panel(app, "Tier 3", None)
gui_2.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"
assert "T-002" in text_args, "imgui.text not called with 'T-002' worker sub-header"
+20 -30
View File
@@ -1,42 +1,32 @@
import pytest
import inspect
def test_session_hub_window_removed():
import src.gui_2 as gui_2
source = inspect.getsource(gui_2.App._render_main_interface)
assert "Session Hub" not in source, "Session Hub window should be removed"
import src.gui_2 as gui_2
source = inspect.getsource(gui_2.render_main_interface)
assert "Session Hub" not in source, "Session Hub window should be removed"
def test_discussion_hub_has_snapshot_tab():
import src.gui_2 as gui_2
source = inspect.getsource(gui_2.App._render_discussion_hub)
assert "Snapshot" in source, "Discussion Hub should have Snapshot tab"
assert "_render_snapshot_tab" in source, "Discussion Hub should call _render_snapshot_tab"
import src.gui_2 as gui_2
source = inspect.getsource(gui_2.render_discussion_hub)
assert "Snapshot" in source, "Discussion Hub should have Snapshot tab"
assert "render_snapshot_tab" in source, "Discussion Hub should call render_snapshot_tab"
def test_discussion_hub_has_context_composition_placeholder():
import src.gui_2 as gui_2
source = inspect.getsource(gui_2.App._render_discussion_hub)
assert "Context Composition" in source, (
"Discussion Hub should have Context Composition tab placeholder"
)
import src.gui_2 as gui_2
source = inspect.getsource(gui_2.render_discussion_hub)
assert "Context Composition" in source, (
"Discussion Hub should have Context Composition tab placeholder"
)
def test_discussion_hub_has_takes_tab():
import src.gui_2 as gui_2
source = inspect.getsource(gui_2.App._render_discussion_hub)
assert "Takes" in source, "Discussion Hub should have Takes tab"
import src.gui_2 as gui_2
source = inspect.getsource(gui_2.render_discussion_hub)
assert "Takes" in source, "Discussion Hub should have Takes tab"
def test_show_windows_no_session_hub():
import src.app_controller as app_controller
source = inspect.getsource(app_controller.AppController)
assert "Session Hub" not in source, (
"Session Hub should be removed from show_windows"
)
import src.app_controller as app_controller
source = inspect.getsource(app_controller.AppController)
assert "Session Hub" not in source, (
"Session Hub should be removed from show_windows"
)
+3 -2
View File
@@ -1,8 +1,9 @@
import pytest
from unittest.mock import patch, MagicMock
from src import gui_2
from src.gui_2 import App
def test_shader_live_editor_renders():
from src.gui_2 import App
app = App()
app.show_windows["Shader Editor"] = True
@@ -20,5 +21,5 @@ def test_shader_live_editor_renders():
mock_imscope.style_color.return_value.__enter__.return_value = None
mock_imscope.style_var.return_value.__enter__.return_value = None
app._render_shader_live_editor()
gui_2.render_shader_live_editor(app)
assert mock_imscope.window.called
+7 -8
View File
@@ -1,16 +1,15 @@
import pytest
import inspect
from src import gui_2
def test_takes_tab_replaces_placeholder():
import src.gui_2 as gui_2
source = inspect.getsource(gui_2.App._gui_func)
assert "_render_takes_placeholder" not in source, "Placeholder should be replaced"
import src.gui_2 as gui_2
source = inspect.getsource(gui_2.App._gui_func)
assert "_render_takes_placeholder" not in source, "Placeholder should be replaced"
def test_takes_panel_has_synthesis():
import src.gui_2 as gui_2
import src.gui_2 as gui_2
source = inspect.getsource(gui_2.App._render_takes_panel)
assert "synthesis" in source.lower(), "Should have synthesis functionality"
source = inspect.getsource(gui_2.render_takes_panel)
assert "synthesis" in source.lower(), "Should have synthesis functionality"