import unittest.mock from unittest.mock import MagicMock, patch from src.gui_2 import App, render_ast_inspector_modal from src import models def test_ast_inspector_line_range_parsing(): # 1. Setup mock App instance app = MagicMock(spec=App) app._show_ast_inspector = True app.show_structural_editor_modal = True app.ui_inspecting_ast_file = models.FileItem(path="test.py") app.ui_editing_slices_file = app.ui_inspecting_ast_file app._cached_ast_file_path = "" app._cached_ast_nodes = [] app._cached_ast_file_lines = [] app.text_viewer_content = "" # Setup mock controller app.controller = MagicMock() app.controller.active_project_path = "C:/projects/test/manual_slop.toml" app.controller.project = {"context_tags": ["auto-ast", "bug"]} # 2. Define mock outline string with line ranges mock_outline = "[Func] foo (Lines 10-20)\n [Class] Bar (Lines 30-50)" # 3. Patch imgui and mcp_client with patch("src.gui_2.imgui") as mock_imgui, \ patch("src.gui_2.imscope") as mock_imscope, \ patch("src.gui_2.mcp_client.py_get_code_outline", return_value=mock_outline), \ patch("src.gui_2.mcp_client.read_file", return_value="test content"): # begin_popup_modal needs to return (expanded, opened) mock_imgui.begin_popup_modal.return_value = (True, True) # begin_child returns True usually mock_imgui.begin_child.return_value = True # radio_button returns (changed, active) mock_imgui.radio_button.return_value = (False, False) mock_imgui.get_content_region_avail.return_value.y = 800.0 mock_imgui.get_frame_height_with_spacing.return_value = 24.0 mock_imgui.get_style.return_value.window_padding = mock_imgui.ImVec2(8,8) # Setup imscope mocks 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 # 4. Call the method render_ast_inspector_modal(app) # 5. Assertions assert len(app._cached_ast_nodes) == 2 node1 = app._cached_ast_nodes[0] assert node1['name'] == "foo" assert node1['kind'] == "Func" assert node1['start_line'] == 10 assert node1['end_line'] == 20 node2 = app._cached_ast_nodes[1] assert node2['name'] == "Bar" assert node2['kind'] == "Class" assert node2['start_line'] == 30 assert node2['end_line'] == 50