-
Notifications
You must be signed in to change notification settings - Fork 7
test: Phase 4 QA β comprehensive tests for Phase 3 core fixes #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,61 @@ | ||||||||||||||||||||||||
| """Tests for project name normalization in MCP server.""" | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| import os | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| from brainlayer.mcp import normalize_project_name | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| class TestNormalizeProjectName: | ||||||||||||||||||||||||
| """Test Claude Code path encoding β clean project name.""" | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def test_none_returns_none(self): | ||||||||||||||||||||||||
| assert normalize_project_name(None) is None | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def test_empty_returns_none(self): | ||||||||||||||||||||||||
| assert normalize_project_name("") is None | ||||||||||||||||||||||||
| assert normalize_project_name(" ") is None | ||||||||||||||||||||||||
| assert normalize_project_name("-") is None | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def test_simple_name_passthrough(self): | ||||||||||||||||||||||||
| """Already-clean names pass through unchanged.""" | ||||||||||||||||||||||||
| assert normalize_project_name("golems") == "golems" | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def test_claude_code_encoded_path(self): | ||||||||||||||||||||||||
| """Standard Claude Code path encoding decodes correctly.""" | ||||||||||||||||||||||||
| # This test requires the actual filesystem to have ~/Gits/golems | ||||||||||||||||||||||||
| result = normalize_project_name("-Users-etanheyman-Gits-golems") | ||||||||||||||||||||||||
| assert result == "golems" | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def test_desktop_gits_path(self): | ||||||||||||||||||||||||
| """Old Desktop/Gits paths decode correctly.""" | ||||||||||||||||||||||||
| # Old path β directory may not exist, but first segment is returned | ||||||||||||||||||||||||
| result = normalize_project_name("-Users-etanheyman-Desktop-Gits-golems") | ||||||||||||||||||||||||
| # Either finds the dir or falls back to first segment | ||||||||||||||||||||||||
| assert result is not None | ||||||||||||||||||||||||
|
Comment on lines
+32
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Weak assertion in For π οΈ Proposed fix- # Either finds the dir or falls back to first segment
- assert result is not None
+ assert result == "golems" # Fallback always returns first remaining segmentπ Committable suggestion
Suggested change
π€ Prompt for AI Agents |
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def test_compound_name_with_dashes(self): | ||||||||||||||||||||||||
| """Compound project names with dashes resolve via filesystem check.""" | ||||||||||||||||||||||||
| # Only works if the directory actually exists | ||||||||||||||||||||||||
| home = os.path.expanduser("~") | ||||||||||||||||||||||||
| gits_dir = os.path.join(home, "Gits") | ||||||||||||||||||||||||
| if os.path.isdir(gits_dir): | ||||||||||||||||||||||||
| for entry in os.listdir(gits_dir): | ||||||||||||||||||||||||
| if "-" in entry and os.path.isdir(os.path.join(gits_dir, entry)): | ||||||||||||||||||||||||
| # Test that this compound name resolves correctly | ||||||||||||||||||||||||
| encoded = f"-Users-{os.path.basename(home)}-Gits-{entry.replace('-', '-')}" | ||||||||||||||||||||||||
| # The encoding is just dashes, same as the name | ||||||||||||||||||||||||
| # Just verify it doesn't crash | ||||||||||||||||||||||||
| result = normalize_project_name(encoded) | ||||||||||||||||||||||||
| assert result is not None | ||||||||||||||||||||||||
| break | ||||||||||||||||||||||||
|
Comment on lines
+39
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Two issues:
Use π οΈ Proposed fix def test_compound_name_with_dashes(self):
"""Compound project names with dashes resolve via filesystem check."""
home = os.path.expanduser("~")
gits_dir = os.path.join(home, "Gits")
if not os.path.isdir(gits_dir):
+ pytest.skip("~/Gits not present on this machine")
for entry in os.listdir(gits_dir):
if "-" in entry and os.path.isdir(os.path.join(gits_dir, entry)):
- encoded = f"-Users-{os.path.basename(home)}-Gits-{entry.replace('-', '-')}"
+ # Claude Code encodes path separators as dashes; the name itself uses dashes
+ encoded = f"-Users-{os.path.basename(home)}-Gits-{entry}"
result = normalize_project_name(encoded)
- assert result is not None
+ assert result == entry, f"Expected {entry!r}, got {result!r}"
break
+ else:
+ pytest.skip("No compound-name directories found in ~/Gits")π€ Prompt for AI Agents |
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def test_worktree_suffix_stripped(self): | ||||||||||||||||||||||||
| """Worktree suffixes are stripped.""" | ||||||||||||||||||||||||
| assert normalize_project_name("golems-nightshift-1770775282043") == "golems" | ||||||||||||||||||||||||
| assert normalize_project_name("golems-haiku-1770775282043") == "golems" | ||||||||||||||||||||||||
| assert normalize_project_name("golems-worktree-1770775282043") == "golems" | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def test_no_gits_segment_returns_none(self): | ||||||||||||||||||||||||
| """Paths without 'Gits' segment return None.""" | ||||||||||||||||||||||||
| result = normalize_project_name("-Users-etanheyman-Documents-stuff") | ||||||||||||||||||||||||
|
Comment on lines
+11
to
+63
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion | π Major
The following test cases are either identical or near-identical across the two files:
Consider consolidating all normalization tests into a single file to reduce maintenance overhead. π€ Prompt for AI Agents |
||||||||||||||||||||||||
| assert result is None | ||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,50 @@ | ||||||||||||||||||||||||||||||
| """Tests for brainlayer.paths β DB path resolution.""" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| import os | ||||||||||||||||||||||||||||||
| from unittest.mock import patch | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| from brainlayer.paths import get_db_path | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| class TestGetDbPath: | ||||||||||||||||||||||||||||||
| """Test DB path resolution order.""" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def test_env_var_override(self, tmp_path): | ||||||||||||||||||||||||||||||
| """BRAINLAYER_DB env var takes highest priority.""" | ||||||||||||||||||||||||||||||
| db_path = tmp_path / "custom.db" | ||||||||||||||||||||||||||||||
| with patch.dict(os.environ, {"BRAINLAYER_DB": str(db_path)}): | ||||||||||||||||||||||||||||||
| assert get_db_path() == db_path | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def test_legacy_path_if_exists(self, tmp_path): | ||||||||||||||||||||||||||||||
| """Legacy zikaron path used when it exists.""" | ||||||||||||||||||||||||||||||
| legacy = tmp_path / "zikaron.db" | ||||||||||||||||||||||||||||||
| legacy.touch() | ||||||||||||||||||||||||||||||
| with ( | ||||||||||||||||||||||||||||||
| patch.dict(os.environ, {}, clear=True), | ||||||||||||||||||||||||||||||
| patch("brainlayer.paths._LEGACY_DB_PATH", legacy), | ||||||||||||||||||||||||||||||
| patch("brainlayer.paths._CANONICAL_DB_PATH", tmp_path / "brainlayer.db"), | ||||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||||
| # Remove env var if set | ||||||||||||||||||||||||||||||
| os.environ.pop("BRAINLAYER_DB", None) | ||||||||||||||||||||||||||||||
| assert get_db_path() == legacy | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def test_canonical_path_fresh_install(self, tmp_path): | ||||||||||||||||||||||||||||||
| """Canonical path used when no legacy DB exists.""" | ||||||||||||||||||||||||||||||
| canonical = tmp_path / "brainlayer" / "brainlayer.db" | ||||||||||||||||||||||||||||||
| legacy = tmp_path / "nonexistent" / "zikaron.db" | ||||||||||||||||||||||||||||||
| with ( | ||||||||||||||||||||||||||||||
| patch.dict(os.environ, {}, clear=True), | ||||||||||||||||||||||||||||||
| patch("brainlayer.paths._LEGACY_DB_PATH", legacy), | ||||||||||||||||||||||||||||||
| patch("brainlayer.paths._CANONICAL_DB_PATH", canonical), | ||||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||||
| os.environ.pop("BRAINLAYER_DB", None) | ||||||||||||||||||||||||||||||
| result = get_db_path() | ||||||||||||||||||||||||||||||
| assert result == canonical | ||||||||||||||||||||||||||||||
| assert canonical.parent.exists() # Parent dir created | ||||||||||||||||||||||||||||||
|
Comment on lines
+15
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion | π Major
π€ Prompt for AI Agents |
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def test_real_db_exists(self): | ||||||||||||||||||||||||||||||
| """The real production DB exists at the resolved path.""" | ||||||||||||||||||||||||||||||
| from brainlayer.paths import DEFAULT_DB_PATH | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| assert DEFAULT_DB_PATH.exists(), f"DB not found at {DEFAULT_DB_PATH}" | ||||||||||||||||||||||||||||||
| assert DEFAULT_DB_PATH.stat().st_size > 1_000_000, "DB too small β might be empty" | ||||||||||||||||||||||||||||||
|
Comment on lines
+48
to
+52
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π§© Analysis chainπ Script executed: # First, find brainlayer/paths.py and check for DEFAULT_DB_PATH
find . -name "paths.py" -type f | grep -E "brainlayer|src"Repository: EtanHey/brainlayer Length of output: 87 π Script executed: # Search for DEFAULT_DB_PATH in the codebase
rg "DEFAULT_DB_PATH" -n --type pyRepository: EtanHey/brainlayer Length of output: 3522 π Script executed: # Get the full content of brainlayer/paths.py to verify what's exported
fd -type f -name "paths.py" -exec grep -n "DEFAULT_DB_PATH\|_LEGACY_DB_PATH\|_CANONICAL_DB_PATH\|^[A-Z_]*.*=" {} +Repository: EtanHey/brainlayer Length of output: 232 π Script executed: # Look at the full test_paths.py file to see all tests and context
cat -n tests/test_paths.pyRepository: EtanHey/brainlayer Length of output: 2371 π Script executed: # Read the full brainlayer/paths.py file
cat -n src/brainlayer/paths.pyRepository: EtanHey/brainlayer Length of output: 1711 π Script executed: # Check for pytest configuration or conftest that might skip tests
find . -name "pytest.ini" -o -name "conftest.py" -o -name "pyproject.toml" | head -10Repository: EtanHey/brainlayer Length of output: 78 π Script executed: # Check CI configuration
find . -name ".github" -type d -o -name ".gitlab-ci.yml" -o -name "*.yml" -path "*/.github/*" | head -20Repository: EtanHey/brainlayer Length of output: 130 π Script executed: # Check the CI workflow configuration
cat -n .github/workflows/ci.ymlRepository: EtanHey/brainlayer Length of output: 983 π Script executed: # Check pyproject.toml for pytest configuration
cat -n pyproject.toml | head -100Repository: EtanHey/brainlayer Length of output: 3373
This test asserts that Gate it with π οΈ Proposed fix+ `@pytest.mark.skipif`(
+ not __import__("brainlayer.paths", fromlist=["DEFAULT_DB_PATH"]).DEFAULT_DB_PATH.exists(),
+ reason="Production DB not present on this machine",
+ )
def test_real_db_exists(self):
"""The real production DB exists at the resolved path."""
from brainlayer.paths import DEFAULT_DB_PATH
assert DEFAULT_DB_PATH.exists(), f"DB not found at {DEFAULT_DB_PATH}"
assert DEFAULT_DB_PATH.stat().st_size > 1_000_000, "DB too small β might be empty"Alternatively, move this to a separate π Committable suggestion
Suggested change
π€ Prompt for AI AgentsThere was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test asserts production DB exists, fails CIMedium Severity
|
||||||||||||||||||||||||||||||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Misleading comment β this test passes on every machine regardless of filesystem.
The comment "This test requires the actual filesystem to have
~/Gits/golems" is incorrect. For the input"-Users-etanheyman-Gits-golems", the implementation triesos.path.isdir("/Users/etanheyman/Gits/golems")and falls back toremaining[0]β which is"golems"β when the directory is absent. The assertionresult == "golems"therefore always passes, not because the directory exists, but due to the fallback. The comment should be corrected to avoid misleading future maintainers.π οΈ Proposed fix
def test_claude_code_encoded_path(self): """Standard Claude Code path encoding decodes correctly.""" - # This test requires the actual filesystem to have ~/Gits/golems + # Falls back to the first remaining segment ("golems") when directory isn't found. result = normalize_project_name("-Users-etanheyman-Gits-golems") assert result == "golems"π€ Prompt for AI Agents