"""Integration test: LSP plugin skips non-local paths. The host-side LSP server can't see files inside Docker/Modal/SSH sandboxes. The plugin's ``_pre_tool_call`` uses ``os.path.exists`` on the parent directory as a heuristic local-only gate. These tests verify the plugin hooks skip when the path clearly doesn't exist on the host filesystem. """ from __future__ import annotations import os import sys from unittest.mock import patch import pytest @pytest.fixture(autouse=True) def _isolate_plugin_state(): """Reset plugin module state between tests.""" # Import the plugin and clear any service state from plugins.lsp import _baselines _baselines.clear() yield _baselines.clear() def test_pre_tool_call_skips_nonexistent_parent_dir(): """pre_tool_call returns early when the path's parent dir doesn't exist (Docker/SSH heuristic).""" from plugins import lsp as lsp_plugin # Simulate a path that doesn't exist on host (e.g., inside Docker) fake_path = "/nonexistent-docker-container-fs/app/main.py" # Mock _ensure_service to return a mock service mock_service = type("MockService", (), { "is_active": lambda self: True, "enabled_for": lambda self, p: True, "snapshot_baseline": lambda self, p: None, })() with patch.object(lsp_plugin, "_service", mock_service): lsp_plugin._pre_tool_call( tool_name="write_file", args={"path": fake_path}, session_id="test-session", tool_call_id="call-1", ) # Baseline should NOT be captured because parent dir doesn't exist assert ("test-session", os.path.normpath(fake_path)) not in lsp_plugin._baselines def test_pre_tool_call_proceeds_for_local_path(tmp_path): """pre_tool_call captures baseline when path exists locally.""" from plugins import lsp as lsp_plugin # Create a real file so the parent-dir check passes test_file = tmp_path / "test.py" test_file.write_text("x = 1\n") mock_service = type("MockService", (), { "is_active": lambda self: True, "enabled_for": lambda self, p: True, "snapshot_baseline": lambda self, p: None, })() with patch.object(lsp_plugin, "_service", mock_service): lsp_plugin._pre_tool_call( tool_name="write_file", args={"path": str(test_file)}, session_id="test-session", tool_call_id="call-2", ) # Baseline SHOULD be captured because the local path exists assert ("test-session", str(test_file)) in lsp_plugin._baselines def test_pre_tool_call_skips_non_write_tools(): """pre_tool_call is a no-op for tools other than write_file/patch.""" from plugins import lsp as lsp_plugin lsp_plugin._pre_tool_call( tool_name="terminal", args={"command": "ls"}, session_id="test-session", tool_call_id="call-3", ) assert len(lsp_plugin._baselines) == 0 def test_pre_tool_call_skips_v4a_patch(): """pre_tool_call skips V4A multi-file patches (has 'patch' key, no 'path' key).""" from plugins import lsp as lsp_plugin mock_service = type("MockService", (), { "is_active": lambda self: True, "enabled_for": lambda self, p: True, "snapshot_baseline": lambda self, p: None, })() with patch.object(lsp_plugin, "_service", mock_service): lsp_plugin._pre_tool_call( tool_name="patch", args={"patch": "*** Begin Patch\n*** Update File: foo.py\n..."}, session_id="test-session", tool_call_id="call-4", ) assert len(lsp_plugin._baselines) == 0 def test_transform_tool_result_injects_diagnostics(tmp_path): """transform_tool_result appends lsp_diagnostics field to JSON result.""" from plugins import lsp as lsp_plugin test_file = tmp_path / "test.py" abs_path = str(test_file) # Pre-populate a baseline entry (simulating pre_tool_call ran) lsp_plugin._baselines.add(("test-session", abs_path)) # Mock service that returns a diagnostic mock_service = type("MockService", (), { "is_active": lambda self: True, "enabled_for": lambda self, p: True, "get_diagnostics_sync": lambda self, p, delta=True, timeout=3.0: [ { "severity": 1, "range": {"start": {"line": 1, "character": 4}}, "message": "Type error: str is not int", "code": "reportReturnType", "source": "Pyright", } ], })() with patch.object(lsp_plugin, "_service", mock_service): result = lsp_plugin._transform_tool_result( tool_name="write_file", args={"path": abs_path}, result='{"bytes_written": 42, "dirs_created": false}', session_id="test-session", tool_call_id="call-5", ) assert result is not None import json data = json.loads(result) assert "lsp_diagnostics" in data assert "reportReturnType" in data["lsp_diagnostics"] assert "bytes_written" in data # Original fields preserved