070c159f11
ROOT CAUSE: render_heavy_text (called per comms panel entry) had manual begin_child/end_child pairs. If anything inside the child (especially markdown_helper.render) raised, end_child was skipped. The child window was left open, corrupting the imGui state. The corruption cascaded through tab_item.end_tab_item -> tab_bar.end_tab_bar -> window.end, triggering 'Must call EndChild() and not End()!' assertion. FIX: Convert the inner begin_child/end_child pair to imscope.child so the end_child is automatically called by Python's with statement, even on exception. Also convert prior_scroll to imscope.child for consistency. TESTS: - Existing test_comms_no_extraneous_pop.py: push/pop balance check - Updated test_prior_session_no_clipping.py to match new imscope.child signature - 28/28 broad regression pass
52 lines
2.5 KiB
Python
52 lines
2.5 KiB
Python
from unittest.mock import patch, MagicMock
|
|
from src.gui_2 import render_prior_session_view
|
|
|
|
def test_prior_session_view_opens_scroll_child_with_explicit_size(app_instance):
|
|
app_instance.prior_disc_entries = [{"role": "User", "content": f"entry {i}", "collapsed": False, "ts": f"t{i}"} for i in range(30)]
|
|
app_instance.perf_profiling_enabled = False
|
|
with patch("src.gui_2.imgui") as mock_imgui, patch("src.gui_2.imscope") as mock_imscope, patch("src.gui_2.theme") as mock_theme:
|
|
_avail = type("P", (), {"x": 800.0, "y": 600.0})()
|
|
mock_imgui.get_content_region_avail = MagicMock(return_value=_avail)
|
|
def _imvec2(x, y=0): m = MagicMock(); m.x = float(x); m.y = float(y); return m
|
|
mock_imgui.ImVec2 = _imvec2
|
|
mock_imscope.style_color = MagicMock()
|
|
mock_imscope.style_color.return_value.__enter__ = MagicMock()
|
|
mock_imscope.style_color.return_value.__exit__ = MagicMock()
|
|
mock_imscope.child = MagicMock()
|
|
mock_imscope.child.return_value.__enter__ = MagicMock()
|
|
mock_imscope.child.return_value.__exit__ = MagicMock()
|
|
mock_imscope.id = MagicMock()
|
|
mock_imscope.id.return_value.__enter__ = MagicMock()
|
|
mock_imscope.id.return_value.__exit__ = MagicMock()
|
|
mock_imgui.button = MagicMock(return_value=False)
|
|
mock_imgui.same_line = MagicMock()
|
|
mock_imgui.text_colored = MagicMock()
|
|
mock_imgui.text = MagicMock()
|
|
mock_imgui.separator = MagicMock()
|
|
_mock_clipper = MagicMock()
|
|
_mock_clipper.step.side_effect = [True, False]
|
|
_mock_clipper.display_start = 0
|
|
_mock_clipper.display_end = 30
|
|
mock_imgui.ListClipper = MagicMock(return_value=_mock_clipper)
|
|
mock_imgui.ListClipper.return_value.begin = MagicMock()
|
|
mock_theme.ai_text_style = MagicMock()
|
|
mock_theme.ai_text_style.return_value.__enter__ = MagicMock()
|
|
mock_theme.ai_text_style.return_value.__exit__ = MagicMock()
|
|
app_instance.controller = MagicMock()
|
|
try:
|
|
render_prior_session_view(app_instance)
|
|
except Exception as e:
|
|
import pytest
|
|
pytest.fail(f"render_prior_session_view raised: {e}")
|
|
assert mock_imscope.child.called, "prior_scroll child should be opened"
|
|
call_args = mock_imscope.child.call_args
|
|
args_list = call_args[0] if call_args[0] else []
|
|
kwargs = call_args[1] if len(call_args) > 1 else {}
|
|
size_arg = args_list[1] if len(args_list) > 1 else kwargs.get("size_x", 0)
|
|
if hasattr(size_arg, 'x'):
|
|
size_x, size_y = size_arg.x, size_arg.y
|
|
else:
|
|
size_x = size_arg
|
|
size_y = kwargs.get("size_y", 0)
|
|
assert size_x == 800.0 and size_y == 600.0, f"prior_scroll should use explicit content region size, got ({size_x}, {size_y})"
|