Files
Claude-Code-Workflow/codex-lens/tests/test_config.py
catlog22 4faa5f1c95 Add comprehensive tests for semantic chunking and search functionality
- Implemented tests for the ChunkConfig and Chunker classes, covering default and custom configurations.
- Added tests for symbol-based chunking, including single and multiple symbols, handling of empty symbols, and preservation of line numbers.
- Developed tests for sliding window chunking, ensuring correct chunking behavior with various content sizes and configurations.
- Created integration tests for semantic search, validating embedding generation, vector storage, and search accuracy across a complex codebase.
- Included performance tests for embedding generation and search operations.
- Established tests for chunking strategies, comparing symbol-based and sliding window approaches.
- Enhanced test coverage for edge cases, including handling of unicode characters and out-of-bounds symbol ranges.
2025-12-12 19:55:35 +08:00

351 lines
14 KiB
Python

"""Tests for CodexLens configuration system."""
import os
import tempfile
from pathlib import Path
import pytest
from codexlens.config import (
WORKSPACE_DIR_NAME,
Config,
WorkspaceConfig,
_default_global_dir,
find_workspace_root,
)
from codexlens.errors import ConfigError
class TestDefaultGlobalDir:
"""Tests for _default_global_dir function."""
def test_default_location(self):
"""Test default location is ~/.codexlens."""
# Clear any environment override
env_backup = os.environ.get("CODEXLENS_DATA_DIR")
if "CODEXLENS_DATA_DIR" in os.environ:
del os.environ["CODEXLENS_DATA_DIR"]
try:
result = _default_global_dir()
assert result == (Path.home() / ".codexlens").resolve()
finally:
if env_backup is not None:
os.environ["CODEXLENS_DATA_DIR"] = env_backup
def test_env_override(self):
"""Test CODEXLENS_DATA_DIR environment variable override."""
with tempfile.TemporaryDirectory() as tmpdir:
os.environ["CODEXLENS_DATA_DIR"] = tmpdir
try:
result = _default_global_dir()
assert result == Path(tmpdir).resolve()
finally:
del os.environ["CODEXLENS_DATA_DIR"]
class TestFindWorkspaceRoot:
"""Tests for find_workspace_root function."""
def test_finds_workspace_in_current_dir(self):
"""Test finding workspace when .codexlens is in current directory."""
with tempfile.TemporaryDirectory() as tmpdir:
base = Path(tmpdir)
(base / WORKSPACE_DIR_NAME).mkdir()
result = find_workspace_root(base)
assert result == base.resolve()
def test_finds_workspace_in_parent_dir(self):
"""Test finding workspace in parent directory."""
with tempfile.TemporaryDirectory() as tmpdir:
base = Path(tmpdir)
(base / WORKSPACE_DIR_NAME).mkdir()
subdir = base / "src" / "components"
subdir.mkdir(parents=True)
result = find_workspace_root(subdir)
assert result == base.resolve()
def test_returns_none_when_not_found(self):
"""Test returns None when no workspace found in isolated directory."""
with tempfile.TemporaryDirectory() as tmpdir:
# Create a deep nested directory to avoid finding user's home .codexlens
isolated = Path(tmpdir) / "a" / "b" / "c"
isolated.mkdir(parents=True)
result = find_workspace_root(isolated)
# May find user's .codexlens if it exists in parent dirs
# So we just check it doesn't find one in our temp directory
if result is not None:
assert WORKSPACE_DIR_NAME not in str(isolated)
def test_does_not_find_file_as_workspace(self):
"""Test that a file named .codexlens is not recognized as workspace."""
with tempfile.TemporaryDirectory() as tmpdir:
base = Path(tmpdir)
# Create isolated subdirectory
subdir = base / "project"
subdir.mkdir()
(subdir / WORKSPACE_DIR_NAME).write_text("not a directory")
result = find_workspace_root(subdir)
# Should not find the file as workspace
if result is not None:
assert result != subdir
class TestConfig:
"""Tests for Config class."""
def test_default_config(self):
"""Test creating config with defaults."""
with tempfile.TemporaryDirectory() as tmpdir:
os.environ["CODEXLENS_DATA_DIR"] = tmpdir
try:
config = Config()
assert config.data_dir == Path(tmpdir).resolve()
assert config.venv_path == Path(tmpdir).resolve() / "venv"
finally:
del os.environ["CODEXLENS_DATA_DIR"]
def test_creates_data_dir(self):
"""Test that data_dir is created on init."""
with tempfile.TemporaryDirectory() as tmpdir:
data_dir = Path(tmpdir) / "new_dir"
config = Config(data_dir=data_dir)
assert data_dir.exists()
def test_supported_languages(self):
"""Test default supported languages."""
with tempfile.TemporaryDirectory() as tmpdir:
os.environ["CODEXLENS_DATA_DIR"] = tmpdir
try:
config = Config()
assert "python" in config.supported_languages
assert "javascript" in config.supported_languages
assert "typescript" in config.supported_languages
assert "java" in config.supported_languages
assert "go" in config.supported_languages
finally:
del os.environ["CODEXLENS_DATA_DIR"]
def test_cache_dir_property(self):
"""Test cache_dir property."""
with tempfile.TemporaryDirectory() as tmpdir:
config = Config(data_dir=Path(tmpdir))
assert config.cache_dir == Path(tmpdir).resolve() / "cache"
def test_index_dir_property(self):
"""Test index_dir property."""
with tempfile.TemporaryDirectory() as tmpdir:
config = Config(data_dir=Path(tmpdir))
assert config.index_dir == Path(tmpdir).resolve() / "index"
def test_db_path_property(self):
"""Test db_path property."""
with tempfile.TemporaryDirectory() as tmpdir:
config = Config(data_dir=Path(tmpdir))
assert config.db_path == Path(tmpdir).resolve() / "index" / "codexlens.db"
def test_ensure_runtime_dirs(self):
"""Test ensure_runtime_dirs creates directories."""
with tempfile.TemporaryDirectory() as tmpdir:
config = Config(data_dir=Path(tmpdir))
config.ensure_runtime_dirs()
assert config.cache_dir.exists()
assert config.index_dir.exists()
def test_language_for_path_python(self):
"""Test language detection for Python files."""
with tempfile.TemporaryDirectory() as tmpdir:
os.environ["CODEXLENS_DATA_DIR"] = tmpdir
try:
config = Config()
assert config.language_for_path("test.py") == "python"
assert config.language_for_path("/path/to/file.py") == "python"
finally:
del os.environ["CODEXLENS_DATA_DIR"]
def test_language_for_path_javascript(self):
"""Test language detection for JavaScript files."""
with tempfile.TemporaryDirectory() as tmpdir:
os.environ["CODEXLENS_DATA_DIR"] = tmpdir
try:
config = Config()
assert config.language_for_path("test.js") == "javascript"
assert config.language_for_path("component.jsx") == "javascript"
finally:
del os.environ["CODEXLENS_DATA_DIR"]
def test_language_for_path_typescript(self):
"""Test language detection for TypeScript files."""
with tempfile.TemporaryDirectory() as tmpdir:
os.environ["CODEXLENS_DATA_DIR"] = tmpdir
try:
config = Config()
assert config.language_for_path("test.ts") == "typescript"
assert config.language_for_path("component.tsx") == "typescript"
finally:
del os.environ["CODEXLENS_DATA_DIR"]
def test_language_for_path_unknown(self):
"""Test language detection for unknown files."""
with tempfile.TemporaryDirectory() as tmpdir:
os.environ["CODEXLENS_DATA_DIR"] = tmpdir
try:
config = Config()
assert config.language_for_path("test.xyz") is None
assert config.language_for_path("README.md") is None
finally:
del os.environ["CODEXLENS_DATA_DIR"]
def test_language_for_path_case_insensitive(self):
"""Test language detection is case insensitive."""
with tempfile.TemporaryDirectory() as tmpdir:
os.environ["CODEXLENS_DATA_DIR"] = tmpdir
try:
config = Config()
assert config.language_for_path("TEST.PY") == "python"
assert config.language_for_path("File.Js") == "javascript"
finally:
del os.environ["CODEXLENS_DATA_DIR"]
def test_rules_for_language(self):
"""Test getting parsing rules for a language."""
with tempfile.TemporaryDirectory() as tmpdir:
os.environ["CODEXLENS_DATA_DIR"] = tmpdir
try:
config = Config()
rules = config.rules_for_language("python")
assert "max_chunk_chars" in rules
assert "max_chunk_lines" in rules
assert "overlap_lines" in rules
finally:
del os.environ["CODEXLENS_DATA_DIR"]
class TestWorkspaceConfig:
"""Tests for WorkspaceConfig class."""
def test_create_workspace_config(self):
"""Test creating a workspace config."""
with tempfile.TemporaryDirectory() as tmpdir:
workspace = WorkspaceConfig(workspace_root=Path(tmpdir))
assert workspace.workspace_root == Path(tmpdir).resolve()
def test_codexlens_dir_property(self):
"""Test codexlens_dir property."""
with tempfile.TemporaryDirectory() as tmpdir:
workspace = WorkspaceConfig(workspace_root=Path(tmpdir))
assert workspace.codexlens_dir == Path(tmpdir).resolve() / WORKSPACE_DIR_NAME
def test_db_path_property(self):
"""Test db_path property."""
with tempfile.TemporaryDirectory() as tmpdir:
workspace = WorkspaceConfig(workspace_root=Path(tmpdir))
expected = Path(tmpdir).resolve() / WORKSPACE_DIR_NAME / "index.db"
assert workspace.db_path == expected
def test_cache_dir_property(self):
"""Test cache_dir property."""
with tempfile.TemporaryDirectory() as tmpdir:
workspace = WorkspaceConfig(workspace_root=Path(tmpdir))
expected = Path(tmpdir).resolve() / WORKSPACE_DIR_NAME / "cache"
assert workspace.cache_dir == expected
def test_initialize_creates_directories(self):
"""Test initialize creates .codexlens directory structure."""
with tempfile.TemporaryDirectory() as tmpdir:
workspace = WorkspaceConfig(workspace_root=Path(tmpdir))
workspace.initialize()
assert workspace.codexlens_dir.exists()
assert workspace.cache_dir.exists()
assert (workspace.codexlens_dir / ".gitignore").exists()
def test_initialize_creates_gitignore(self):
"""Test initialize creates .gitignore with correct content."""
with tempfile.TemporaryDirectory() as tmpdir:
workspace = WorkspaceConfig(workspace_root=Path(tmpdir))
workspace.initialize()
gitignore = workspace.codexlens_dir / ".gitignore"
content = gitignore.read_text()
assert "cache/" in content
def test_exists_false_when_not_initialized(self):
"""Test exists returns False when not initialized."""
with tempfile.TemporaryDirectory() as tmpdir:
workspace = WorkspaceConfig(workspace_root=Path(tmpdir))
assert not workspace.exists()
def test_exists_true_when_initialized_with_db(self):
"""Test exists returns True when initialized with db."""
with tempfile.TemporaryDirectory() as tmpdir:
workspace = WorkspaceConfig(workspace_root=Path(tmpdir))
workspace.initialize()
# Create the db file to simulate full initialization
workspace.db_path.write_text("")
assert workspace.exists()
def test_from_path_finds_workspace(self):
"""Test from_path finds existing workspace."""
with tempfile.TemporaryDirectory() as tmpdir:
base = Path(tmpdir)
(base / WORKSPACE_DIR_NAME).mkdir()
workspace = WorkspaceConfig.from_path(base)
assert workspace is not None
assert workspace.workspace_root == base.resolve()
def test_from_path_returns_none_when_not_found(self):
"""Test from_path returns None when no workspace found in isolated directory."""
with tempfile.TemporaryDirectory() as tmpdir:
# Create isolated directory structure to avoid user's .codexlens
isolated = Path(tmpdir) / "a" / "b" / "c"
isolated.mkdir(parents=True)
workspace = WorkspaceConfig.from_path(isolated)
# May find user's .codexlens if it exists
if workspace is not None:
assert WORKSPACE_DIR_NAME not in str(isolated)
def test_create_at_initializes_workspace(self):
"""Test create_at creates and initializes workspace."""
with tempfile.TemporaryDirectory() as tmpdir:
workspace = WorkspaceConfig.create_at(Path(tmpdir))
assert workspace.codexlens_dir.exists()
assert workspace.cache_dir.exists()
class TestConfigEdgeCases:
"""Edge case tests for configuration."""
def test_config_with_path_object(self):
"""Test Config accepts Path objects."""
with tempfile.TemporaryDirectory() as tmpdir:
config = Config(data_dir=Path(tmpdir))
assert isinstance(config.data_dir, Path)
def test_config_expands_user_path(self):
"""Test Config expands ~ in paths."""
with tempfile.TemporaryDirectory() as tmpdir:
os.environ["CODEXLENS_DATA_DIR"] = tmpdir
try:
config = Config()
# Just verify it doesn't crash and returns a resolved path
assert config.data_dir.is_absolute()
finally:
del os.environ["CODEXLENS_DATA_DIR"]
def test_workspace_config_from_subdir(self):
"""Test WorkspaceConfig.from_path works from subdirectory."""
with tempfile.TemporaryDirectory() as tmpdir:
base = Path(tmpdir)
(base / WORKSPACE_DIR_NAME).mkdir()
deep_subdir = base / "a" / "b" / "c" / "d"
deep_subdir.mkdir(parents=True)
workspace = WorkspaceConfig.from_path(deep_subdir)
assert workspace is not None
assert workspace.workspace_root == base.resolve()