test: Add GUI integration tests for external editor
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
"""Integration test for external editor GUI functionality.
|
||||
|
||||
These tests verify that the external editor configuration is properly
|
||||
loaded and the patch modal shows the option to open in external editor.
|
||||
|
||||
Manual verification:
|
||||
1. Run: uv run sloppy.py
|
||||
2. Ensure config.toml has external editor configured
|
||||
3. Have an agent/Tier 4 generate a patch
|
||||
4. Click "Open in External Editor" in the patch modal
|
||||
5. VSCode should open with diff view showing original vs modified
|
||||
"""
|
||||
import pytest
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "src")))
|
||||
|
||||
from src import api_hook_client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_external_editor_config():
|
||||
return {
|
||||
"ai": {"provider": "gemini", "model": "gemini-2.5-flash-lite"},
|
||||
"projects": {"paths": [], "active": ""},
|
||||
"paths": {"logs_dir": "logs", "scripts_dir": "scripts"},
|
||||
"tools": {
|
||||
"text_editors": {
|
||||
"vscode": {
|
||||
"path": "C:\\apps\\Microsoft VS Code\\Code.exe",
|
||||
"diff_args": ["--new-window", "--diff"]
|
||||
}
|
||||
},
|
||||
"default_editor": {"default_editor": "vscode"}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
@pytest.mark.timeout(120)
|
||||
def test_external_editor_config_shows_in_panel(live_gui, monkeypatch):
|
||||
proc, _ = live_gui
|
||||
client = api_hook_client.ApiHookClient()
|
||||
|
||||
if not client.wait_for_server(timeout=15):
|
||||
pytest.skip("GUI server not available")
|
||||
|
||||
test_config = {
|
||||
"ai": {"provider": "gemini", "model": "gemini-2.5-flash-lite"},
|
||||
"projects": {"paths": [], "active": ""},
|
||||
"paths": {"logs_dir": "logs", "scripts_dir": "scripts"},
|
||||
"tools": {
|
||||
"text_editors": {
|
||||
"vscode": {
|
||||
"path": "C:\\apps\\Microsoft VS Code\\Code.exe",
|
||||
"diff_args": ["--new-window", "--diff"]
|
||||
}
|
||||
},
|
||||
"default_editor": {"default_editor": "vscode"}
|
||||
}
|
||||
}
|
||||
|
||||
import src.models as models_module
|
||||
monkeypatch.setattr(models_module, 'load_config', lambda: test_config)
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
state = client.get_gui_state()
|
||||
print(f"GUI state keys: {list(state.keys())[:10]}...")
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
@pytest.mark.timeout(120)
|
||||
def test_patch_modal_appears_with_external_editor(live_gui, monkeypatch):
|
||||
proc, _ = live_gui
|
||||
client = api_hook_client.ApiHookClient()
|
||||
|
||||
if not client.wait_for_server(timeout=15):
|
||||
pytest.skip("GUI server not available")
|
||||
|
||||
test_config = {
|
||||
"ai": {"provider": "gemini", "model": "gemini-2.5-flash-lite"},
|
||||
"projects": {"paths": [], "active": ""},
|
||||
"paths": {"logs_dir": "logs", "scripts_dir": "scripts"},
|
||||
"tools": {
|
||||
"text_editors": {
|
||||
"vscode": {
|
||||
"path": "C:\\apps\\Microsoft VS Code\\Code.exe",
|
||||
"diff_args": ["--new-window", "--diff"]
|
||||
}
|
||||
},
|
||||
"default_editor": {"default_editor": "vscode"}
|
||||
}
|
||||
}
|
||||
|
||||
import src.models as models_module
|
||||
monkeypatch.setattr(models_module, 'load_config', lambda: test_config)
|
||||
|
||||
sample_patch = """--- a/test_file.py
|
||||
+++ b/test_file.py
|
||||
@@ -1,3 +1,4 @@
|
||||
def hello():
|
||||
- print("old")
|
||||
+ print("new")
|
||||
+ print("extra")
|
||||
return True"""
|
||||
|
||||
client.push_event("show_patch_modal", {
|
||||
"patch_text": sample_patch,
|
||||
"file_paths": ["test_file.py"]
|
||||
})
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
state = client.get_gui_state()
|
||||
assert state.get("_show_patch_modal") == True, f"Patch modal should be visible: {state}"
|
||||
assert state.get("_pending_patch_text") is not None, "Pending patch text should be set"
|
||||
|
||||
print("Patch modal visible with external editor configured")
|
||||
print("To manually test: Click 'Open in External Editor' button to launch VSCode")
|
||||
|
||||
client.push_event("hide_patch_modal", {})
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
@pytest.mark.timeout(120)
|
||||
def test_verify_vscode_diff_command_format(live_gui):
|
||||
from src.external_editor import ExternalEditorLauncher, ExternalEditorConfig, TextEditorConfig
|
||||
|
||||
config = ExternalEditorConfig(
|
||||
editors={
|
||||
"vscode": TextEditorConfig(
|
||||
name="vscode",
|
||||
path="C:\\apps\\Microsoft VS Code\\Code.exe",
|
||||
diff_args=["--new-window", "--diff"]
|
||||
)
|
||||
},
|
||||
default_editor="vscode"
|
||||
)
|
||||
launcher = ExternalEditorLauncher(config)
|
||||
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False, encoding="utf-8") as f:
|
||||
f.write("original\n")
|
||||
orig = f.name
|
||||
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix="_modified.txt", delete=False, encoding="utf-8") as f:
|
||||
f.write("modified\n")
|
||||
mod = f.name
|
||||
|
||||
try:
|
||||
cmd = launcher.build_diff_command(
|
||||
launcher.config.editors["vscode"],
|
||||
orig,
|
||||
mod
|
||||
)
|
||||
assert "--diff" in cmd, f"VSCode command should include --diff: {cmd}"
|
||||
assert "Code.exe" in cmd[0], f"Should launch Code.exe: {cmd}"
|
||||
print(f"VSCode diff command correctly formatted: {cmd}")
|
||||
finally:
|
||||
os.unlink(orig)
|
||||
os.unlink(mod)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v", "-s"])
|
||||
Reference in New Issue
Block a user