171 lines
5.3 KiB
Python
171 lines
5.3 KiB
Python
"""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"])
|