8f11340b38
Per post_module_taxonomy_de_cruft_20260627 Phase 2 (FR7). Each
'from src.models import X' for a moved class is rewritten to
'from src.<destination> import X':
Ticket, Track, WorkerContext, TrackState, TrackMetadata,
ThinkingSegment, EMPTY_TRACK_STATE -> src.mma
ProjectContext, ProjectMeta, ProjectOutput, ProjectFiles,
ProjectScreenshots, ProjectDiscussion, EMPTY_PROJECT_CONTEXT -> src.project
FileItem, Preset, ContextPreset, ContextFileEntry,
NamedViewPreset -> src.project_files
Tool, ToolPreset -> src.tool_presets
BiasProfile -> src.tool_bias
TextEditorConfig, ExternalEditorConfig,
EMPTY_TEXT_EDITOR_CONFIG -> src.external_editor
Persona -> src.personas
WorkspaceProfile -> src.workspace_manager
MCPServerConfig, MCPConfiguration, VectorStoreConfig,
RAGConfig, load_mcp_config -> src.mcp_client
NOT touched (kept on src.models; Phase 3 or Phase 4 will move them):
GenerateRequest, ConfirmRequest, DEFAULT_TOOL_CATEGORIES, Metadata, PROVIDERS
Migration was performed by the one-time script
scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/migrate_imports.py
which uses a class-to-module map and re.sub() to rewrite each
'from src.models import X' line.
Total: 85 import lines rewritten across 71 files.
Note: this commit depends on the v2 SHIPPED work
(origin/tier2/module_taxonomy_refactor_20260627) being merged into
this branch NEXT. On master (without the v2 SHIPPED commits), the
destination modules do not exist and these imports would fail.
105 lines
4.2 KiB
Python
105 lines
4.2 KiB
Python
import pytest
|
|
from unittest.mock import Mock
|
|
from pathlib import Path
|
|
from src.gui_2 import App
|
|
from src.project_files import FileItem
|
|
|
|
def test_preview_button_syncs_context_files_to_controller():
|
|
app = Mock(spec=App)
|
|
app.context_files = [FileItem(path='test.py', view_mode='summary')]
|
|
app.files = []
|
|
app.controller = Mock()
|
|
app.controller.context_files = []
|
|
app.controller._do_generate.return_value = ('# Test Content', Path('.'), [], '', '')
|
|
app.show_windows = {'Context Preview': False}
|
|
app.ui_selected_context_files = set()
|
|
|
|
from src.gui_2 import render_context_batch_actions
|
|
import unittest.mock as mock
|
|
with mock.patch('src.gui_2.imgui') as mock_imgui:
|
|
mock_imgui.button.return_value = True
|
|
mock_imgui.same_line = mock.Mock()
|
|
mock_imgui.text = mock.Mock()
|
|
mock_imgui.open_popup = mock.Mock()
|
|
render_context_batch_actions(app, 100, 50)
|
|
assert len(app.controller.context_files) == 1
|
|
assert app.controller.context_files[0].path == 'test.py'
|
|
|
|
def test_preview_button_empty_state_message():
|
|
app = Mock(spec=App)
|
|
app.context_files = []
|
|
app.files = []
|
|
app.controller = Mock()
|
|
app.controller.context_files = []
|
|
app.controller._do_generate.return_value = ('', Path('.'), [], '', '')
|
|
app.show_windows = {'Context Preview': False}
|
|
app.context_preview_text = None
|
|
app.ui_selected_context_files = set()
|
|
|
|
from src.gui_2 import render_context_batch_actions
|
|
import unittest.mock as mock
|
|
with mock.patch('src.gui_2.imgui') as mock_imgui:
|
|
mock_imgui.button.return_value = True
|
|
mock_imgui.same_line = mock.Mock()
|
|
mock_imgui.text = mock.Mock()
|
|
mock_imgui.open_popup = mock.Mock()
|
|
render_context_batch_actions(app, 0, 0)
|
|
assert app.context_preview_text == '' or 'No files' in str(app.context_preview_text)
|
|
|
|
|
|
def test_preview_generates_nonempty_for_real_files(monkeypatch):
|
|
"""Integration test: Preview button should generate content when context_files has real FileItems."""
|
|
import src.project_manager as pm
|
|
import src.aggregate as agg
|
|
from src.project_files import FileItem
|
|
|
|
app = Mock(spec=App)
|
|
test_file = FileItem(path='tests/test_context_composition_decoupled.py', view_mode='summary')
|
|
app.context_files = [test_file]
|
|
app.files = []
|
|
app.controller = Mock()
|
|
app.controller.context_files = []
|
|
app.show_windows = {'Context Preview': False}
|
|
app.ui_selected_context_files = set()
|
|
|
|
def mock_flat_config(*args, **kwargs):
|
|
return {'files': {}, 'project': {}, 'output': {'output_dir': 'tests/artifacts'}, 'discussion': {'history': []}}
|
|
|
|
def mock_aggregate_run(flat, **kwargs):
|
|
paths = flat['files']['paths']
|
|
assert len(paths) == 1
|
|
assert paths[0].path == 'tests/test_context_composition_decoupled.py'
|
|
return ('Generated Markdown Content', Path('tests/artifacts/output.md'), [])
|
|
|
|
app.controller._do_generate.return_value = ('Generated Markdown Content', Path('tests/artifacts/output.md'), [], '', '')
|
|
monkeypatch.setattr(pm, 'flat_config', mock_flat_config)
|
|
monkeypatch.setattr(pm, 'save_project', lambda *args: None)
|
|
monkeypatch.setattr(agg, 'run', mock_aggregate_run)
|
|
monkeypatch.setattr(agg, 'build_markdown_no_history', lambda *args, **kwargs: 'stable')
|
|
monkeypatch.setattr(agg, 'build_discussion_text', lambda *args, **kwargs: 'disc')
|
|
|
|
from src.gui_2 import render_context_batch_actions
|
|
import unittest.mock as mock
|
|
with mock.patch('src.gui_2.imgui') as mock_imgui:
|
|
mock_imgui.button.return_value = True
|
|
mock_imgui.same_line = mock.Mock()
|
|
mock_imgui.text = mock.Mock()
|
|
mock_imgui.open_popup = mock.Mock()
|
|
render_context_batch_actions(app, 100, 50)
|
|
assert app.context_preview_text == 'Generated Markdown Content'
|
|
assert app.controller.context_files == app.context_files
|
|
|
|
def test_text_viewer_window_invoked_in_render_loop():
|
|
import src.gui_2 as gui_2
|
|
assert hasattr(gui_2, 'render_text_viewer_window'), "render_text_viewer_window function must exist"
|
|
assert callable(gui_2.render_text_viewer_window), "render_text_viewer_window must be callable"
|
|
import re
|
|
with open('src/gui_2.py', 'r', encoding='utf-8', newline='') as f:
|
|
content = f.read()
|
|
call_pattern = r'render_text_viewer_window\(app\)'
|
|
matches = list(re.finditer(call_pattern, content))
|
|
assert len(matches) >= 1, f"render_text_viewer_window should be called at least once in the main render loop, found {len(matches)}"
|
|
|
|
if __name__ == '__main__':
|
|
pytest.main([__file__, '-v'])
|