138 lines
4.4 KiB
Python
138 lines
4.4 KiB
Python
"""
|
|
Tests for BaseCompletionEngine.
|
|
|
|
Uses a mock implementation to test the abstract base class functionality.
|
|
"""
|
|
|
|
import pytest
|
|
from typing import Any
|
|
|
|
from myfasthtml.core.dsl.types import Position, Suggestion, CompletionResult
|
|
from myfasthtml.core.dsl.base_completion import BaseCompletionEngine
|
|
from myfasthtml.core.dsl.base_provider import BaseMetadataProvider
|
|
|
|
|
|
class MockProvider:
|
|
"""Mock metadata provider for testing."""
|
|
|
|
def get_style_presets(self) -> list[str]:
|
|
return ["custom_highlight"]
|
|
|
|
def get_format_presets(self) -> list[str]:
|
|
return ["CHF"]
|
|
|
|
|
|
class MockCompletionEngine(BaseCompletionEngine):
|
|
"""Mock completion engine for testing base class functionality."""
|
|
|
|
def __init__(self, provider: BaseMetadataProvider, suggestions: list[Suggestion] = None):
|
|
super().__init__(provider)
|
|
self._suggestions = suggestions or []
|
|
self._scope = None
|
|
self._context = "test_context"
|
|
|
|
def detect_scope(self, text: str, current_line: int) -> Any:
|
|
return self._scope
|
|
|
|
def detect_context(self, text: str, cursor: Position, scope: Any) -> Any:
|
|
return self._context
|
|
|
|
def get_suggestions(self, context: Any, scope: Any, prefix: str) -> list[Suggestion]:
|
|
return self._suggestions
|
|
|
|
|
|
# =============================================================================
|
|
# Filter Suggestions Tests
|
|
# =============================================================================
|
|
|
|
|
|
def test_i_can_filter_suggestions_by_prefix():
|
|
"""Test that _filter_suggestions filters case-insensitively."""
|
|
provider = MockProvider()
|
|
engine = MockCompletionEngine(provider)
|
|
|
|
suggestions = [
|
|
Suggestion("primary", "Primary color", "preset"),
|
|
Suggestion("error", "Error color", "preset"),
|
|
Suggestion("warning", "Warning color", "preset"),
|
|
Suggestion("Error", "Title case error", "preset"),
|
|
]
|
|
|
|
# Filter by "err" - should match "error" and "Error" (case-insensitive)
|
|
filtered = engine._filter_suggestions(suggestions, "err")
|
|
labels = [s.label for s in filtered]
|
|
assert "error" in labels
|
|
assert "Error" in labels
|
|
assert "primary" not in labels
|
|
assert "warning" not in labels
|
|
|
|
|
|
def test_i_can_filter_suggestions_empty_prefix():
|
|
"""Test that empty prefix returns all suggestions."""
|
|
provider = MockProvider()
|
|
engine = MockCompletionEngine(provider)
|
|
|
|
suggestions = [
|
|
Suggestion("a"),
|
|
Suggestion("b"),
|
|
Suggestion("c"),
|
|
]
|
|
|
|
filtered = engine._filter_suggestions(suggestions, "")
|
|
assert len(filtered) == 3
|
|
|
|
|
|
# =============================================================================
|
|
# Empty Result Tests
|
|
# =============================================================================
|
|
|
|
|
|
def test_i_can_get_empty_result():
|
|
"""Test that _empty_result returns a CompletionResult with no suggestions."""
|
|
provider = MockProvider()
|
|
engine = MockCompletionEngine(provider)
|
|
|
|
cursor = Position(line=5, ch=10)
|
|
result = engine._empty_result(cursor)
|
|
|
|
assert result.from_pos == cursor
|
|
assert result.to_pos == cursor
|
|
assert result.suggestions == []
|
|
assert result.is_empty is True
|
|
|
|
|
|
# =============================================================================
|
|
# Comment Skipping Tests
|
|
# =============================================================================
|
|
|
|
|
|
def test_i_can_skip_completion_in_comment():
|
|
"""Test that get_completions returns empty when cursor is in a comment."""
|
|
provider = MockProvider()
|
|
suggestions = [Suggestion("should_not_appear")]
|
|
engine = MockCompletionEngine(provider, suggestions)
|
|
|
|
text = "# This is a comment"
|
|
cursor = Position(line=0, ch=15) # Inside the comment
|
|
|
|
result = engine.get_completions(text, cursor)
|
|
|
|
assert result.is_empty is True
|
|
assert len(result.suggestions) == 0
|
|
|
|
|
|
def test_i_can_get_completions_outside_comment():
|
|
"""Test that get_completions works when cursor is not in a comment."""
|
|
provider = MockProvider()
|
|
suggestions = [Suggestion("style"), Suggestion("format")]
|
|
engine = MockCompletionEngine(provider, suggestions)
|
|
|
|
# Cursor at space (ch=5) so prefix is empty and all suggestions are returned
|
|
text = "text # comment"
|
|
cursor = Position(line=0, ch=5) # At empty space, before comment
|
|
|
|
result = engine.get_completions(text, cursor)
|
|
|
|
assert result.is_empty is False
|
|
assert len(result.suggestions) == 2
|