"""Step definitions for lsp_tool_adapter_coverage.feature. Covers uncovered lines in src/cleveragents/lsp/tool_adapter.py: - Line 198: ValueError when config is None - Lines 126-132: workspace-symbols handler (empty query / valid query) - Line 137: missing file_path guard - Line 141: diagnostics delegation - Lines 143-147: completions delegation - Lines 150-153: unimplemented capability fallback """ from __future__ import annotations from unittest.mock import MagicMock from behave import given, then, when from cleveragents.lsp.errors import LspNotAvailableError from cleveragents.lsp.models import LspCapability from cleveragents.lsp.tool_adapter import ( LspToolAdapter, _make_runtime_handler, ) # --------------------------------------------------------------------------- # Givens # --------------------------------------------------------------------------- _SERVER_NAME = "test/mock-server" @given("ltacov an LspToolAdapter with no runtime") def step_ltacov_adapter_no_runtime(context): context.ltacov_adapter = LspToolAdapter(runtime=None) @given("ltacov a mock LspRuntime") def step_ltacov_mock_runtime(context): context.ltacov_runtime = MagicMock() context.ltacov_runtime.get_diagnostics = MagicMock(return_value=[]) context.ltacov_runtime.get_completions = MagicMock(return_value=[]) @given("ltacov the runtime get_diagnostics returns sample items") def step_ltacov_diagnostics_returns_items(context): context.ltacov_sample_items = [{"message": "unused import", "severity": 2}] context.ltacov_runtime.get_diagnostics.return_value = context.ltacov_sample_items @given("ltacov the runtime get_completions returns sample items") def step_ltacov_completions_returns_items(context): context.ltacov_sample_items = [{"label": "my_func", "kind": 3}] context.ltacov_runtime.get_completions.return_value = context.ltacov_sample_items @given("ltacov a runtime handler for workspace_symbols capability") def step_ltacov_handler_workspace_symbols(context): context.ltacov_handler = _make_runtime_handler( context.ltacov_runtime, _SERVER_NAME, LspCapability.WORKSPACE_SYMBOLS ) @given("ltacov a runtime handler for diagnostics capability") def step_ltacov_handler_diagnostics(context): context.ltacov_handler = _make_runtime_handler( context.ltacov_runtime, _SERVER_NAME, LspCapability.DIAGNOSTICS ) @given("ltacov a runtime handler for completions capability") def step_ltacov_handler_completions(context): context.ltacov_handler = _make_runtime_handler( context.ltacov_runtime, _SERVER_NAME, LspCapability.COMPLETIONS ) @given("ltacov a runtime handler for hover capability") def step_ltacov_handler_hover(context): context.ltacov_handler = _make_runtime_handler( context.ltacov_runtime, _SERVER_NAME, LspCapability.HOVER ) @given("ltacov a runtime handler for references capability") def step_ltacov_handler_references(context): context.ltacov_handler = _make_runtime_handler( context.ltacov_runtime, _SERVER_NAME, LspCapability.REFERENCES ) # --------------------------------------------------------------------------- # Whens # --------------------------------------------------------------------------- @when("ltacov generate_tool_specs is called with None config") def step_ltacov_generate_with_none(context): context.ltacov_error = None try: context.ltacov_adapter.generate_tool_specs(None) except ValueError as exc: context.ltacov_error = exc @when("ltacov the handler is called with no query argument") def step_ltacov_handler_no_query(context): context.ltacov_error = None context.ltacov_result = None try: context.ltacov_result = context.ltacov_handler() except Exception as exc: context.ltacov_error = exc @when('ltacov the handler is called with query "{query}"') def step_ltacov_handler_with_query(context, query): context.ltacov_error = None context.ltacov_result = None try: context.ltacov_result = context.ltacov_handler(query=query) except LspNotAvailableError as exc: context.ltacov_error = exc @when("ltacov the handler is called with no file_path argument") def step_ltacov_handler_no_filepath(context): context.ltacov_error = None context.ltacov_result = None try: context.ltacov_result = context.ltacov_handler() except Exception as exc: context.ltacov_error = exc @when('ltacov the handler is called with file_path "{file_path}"') def step_ltacov_handler_with_filepath(context, file_path): context.ltacov_error = None context.ltacov_result = None try: context.ltacov_result = context.ltacov_handler(file_path=file_path) except LspNotAvailableError as exc: context.ltacov_error = exc @when( 'ltacov the handler is called with file_path "{file_path}" line {line:d} column {column:d}' ) def step_ltacov_handler_with_filepath_line_col(context, file_path, line, column): context.ltacov_error = None context.ltacov_result = None try: context.ltacov_result = context.ltacov_handler( file_path=file_path, line=line, column=column ) except LspNotAvailableError as exc: context.ltacov_error = exc # --------------------------------------------------------------------------- # Thens # --------------------------------------------------------------------------- @then('ltacov a ValueError with message "{msg}" is raised') def step_ltacov_valueerror_raised(context, msg): assert context.ltacov_error is not None, "Expected a ValueError but none was raised" assert isinstance(context.ltacov_error, ValueError), ( f"Expected ValueError, got {type(context.ltacov_error).__name__}" ) assert msg in str(context.ltacov_error), ( f"Expected message to contain '{msg}', got '{context.ltacov_error}'" ) @then('ltacov the result is an error dict saying "{expected_msg}"') def step_ltacov_error_dict(context, expected_msg): assert context.ltacov_error is None, ( f"Expected no exception, but got {context.ltacov_error}" ) assert isinstance(context.ltacov_result, dict), ( f"Expected dict, got {type(context.ltacov_result)}" ) assert "error" in context.ltacov_result, ( f"Expected 'error' key in result: {context.ltacov_result}" ) assert expected_msg in context.ltacov_result["error"], ( f"Expected error to contain '{expected_msg}', " f"got '{context.ltacov_result['error']}'" ) @then('ltacov an LspNotAvailableError is raised mentioning "{capability}"') def step_ltacov_lsp_not_available(context, capability): assert context.ltacov_error is not None, ( "Expected LspNotAvailableError but none was raised" ) assert isinstance(context.ltacov_error, LspNotAvailableError), ( f"Expected LspNotAvailableError, got {type(context.ltacov_error).__name__}" ) assert capability in str(context.ltacov_error), ( f"Expected error message to mention '{capability}', " f"got '{context.ltacov_error}'" ) @then('ltacov the result contains a "{key}" key with the sample items') def step_ltacov_result_with_key(context, key): assert context.ltacov_error is None, ( f"Expected no exception, but got {context.ltacov_error}" ) assert isinstance(context.ltacov_result, dict), ( f"Expected dict, got {type(context.ltacov_result)}" ) assert key in context.ltacov_result, ( f"Expected key '{key}' in result: {context.ltacov_result}" ) assert context.ltacov_result[key] == context.ltacov_sample_items, ( f"Expected {context.ltacov_sample_items}, got {context.ltacov_result[key]}" )