mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
1856d4b462
The htop-inspired dashboard (3004d0d1) changed the project info output
from "Basic Memory Project Info" / "Statistics" to project name title
with "Knowledge Graph" section. Update test assertions to match.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
174 lines
6.4 KiB
Python
174 lines
6.4 KiB
Python
"""Integration tests for project CLI commands."""
|
|
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
from typer.testing import CliRunner
|
|
|
|
from basic_memory.cli.main import app as cli_app
|
|
|
|
WIDE_TERMINAL_ENV = {"COLUMNS": "240", "LINES": "60"}
|
|
|
|
|
|
def test_project_list(app, app_config, test_project, config_manager):
|
|
"""Test 'bm project list' command shows projects."""
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli_app, ["project", "list"], env=WIDE_TERMINAL_ENV)
|
|
|
|
if result.exit_code != 0:
|
|
print(f"STDOUT: {result.stdout}")
|
|
print(f"STDERR: {result.stderr}")
|
|
print(f"Exception: {result.exception}")
|
|
assert result.exit_code == 0
|
|
assert "test-project" in result.stdout
|
|
assert "[X]" in result.stdout # default marker
|
|
|
|
|
|
def test_project_info(app, app_config, test_project, config_manager):
|
|
"""Test 'bm project info' command shows project details."""
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli_app, ["project", "info", "test-project"])
|
|
|
|
if result.exit_code != 0:
|
|
print(f"STDOUT: {result.stdout}")
|
|
print(f"STDERR: {result.stderr}")
|
|
assert result.exit_code == 0
|
|
assert "test-project" in result.stdout
|
|
assert "Knowledge Graph" in result.stdout
|
|
|
|
|
|
def test_project_info_json(app, app_config, test_project, config_manager):
|
|
"""Test 'bm project info --json' command outputs valid JSON."""
|
|
import json
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli_app, ["project", "info", "test-project", "--json"])
|
|
|
|
if result.exit_code != 0:
|
|
print(f"STDOUT: {result.stdout}")
|
|
print(f"STDERR: {result.stderr}")
|
|
assert result.exit_code == 0
|
|
|
|
# Parse JSON to verify it's valid
|
|
data = json.loads(result.stdout)
|
|
assert data["project_name"] == "test-project"
|
|
assert "statistics" in data
|
|
assert "system" in data
|
|
|
|
|
|
def test_project_add_and_remove(app, app_config, config_manager):
|
|
"""Test adding and removing a project."""
|
|
runner = CliRunner()
|
|
|
|
# Use a separate temporary directory to avoid nested path conflicts
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
new_project_path = Path(temp_dir) / "new-project"
|
|
new_project_path.mkdir()
|
|
|
|
# Add project
|
|
result = runner.invoke(cli_app, ["project", "add", "new-project", str(new_project_path)])
|
|
|
|
if result.exit_code != 0:
|
|
print(f"STDOUT: {result.stdout}")
|
|
print(f"STDERR: {result.stderr}")
|
|
assert result.exit_code == 0
|
|
assert (
|
|
"Project 'new-project' added successfully" in result.stdout
|
|
or "added" in result.stdout.lower()
|
|
)
|
|
|
|
# Verify it shows up in list
|
|
result = runner.invoke(cli_app, ["project", "list"], env=WIDE_TERMINAL_ENV)
|
|
assert result.exit_code == 0
|
|
assert "new-project" in result.stdout
|
|
|
|
# Remove project
|
|
result = runner.invoke(cli_app, ["project", "remove", "new-project"])
|
|
assert result.exit_code == 0
|
|
assert "removed" in result.stdout.lower() or "deleted" in result.stdout.lower()
|
|
|
|
|
|
def test_project_set_default(app, app_config, config_manager):
|
|
"""Test setting default project."""
|
|
runner = CliRunner()
|
|
|
|
# Use a separate temporary directory to avoid nested path conflicts
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
new_project_path = Path(temp_dir) / "another-project"
|
|
new_project_path.mkdir()
|
|
|
|
# Add a second project
|
|
result = runner.invoke(
|
|
cli_app, ["project", "add", "another-project", str(new_project_path)]
|
|
)
|
|
if result.exit_code != 0:
|
|
print(f"STDOUT: {result.stdout}")
|
|
print(f"STDERR: {result.stderr}")
|
|
assert result.exit_code == 0
|
|
|
|
# Set as default
|
|
result = runner.invoke(cli_app, ["project", "default", "another-project"])
|
|
if result.exit_code != 0:
|
|
print(f"STDOUT: {result.stdout}")
|
|
print(f"STDERR: {result.stderr}")
|
|
assert result.exit_code == 0
|
|
assert "default" in result.stdout.lower()
|
|
|
|
# Verify in list
|
|
result = runner.invoke(cli_app, ["project", "list"], env=WIDE_TERMINAL_ENV)
|
|
assert result.exit_code == 0
|
|
# The new project should have the [X] marker now
|
|
lines = result.stdout.split("\n")
|
|
for line in lines:
|
|
if "another-project" in line:
|
|
assert "[X]" in line
|
|
|
|
|
|
def test_remove_main_project(app, app_config, config_manager):
|
|
"""Test that removing main project then listing projects prevents main from reappearing (issue #397)."""
|
|
runner = CliRunner()
|
|
|
|
# Create separate temp dirs for each project
|
|
with (
|
|
tempfile.TemporaryDirectory() as main_dir,
|
|
tempfile.TemporaryDirectory() as new_default_dir,
|
|
):
|
|
main_path = Path(main_dir)
|
|
new_default_path = Path(new_default_dir)
|
|
|
|
# Ensure main exists
|
|
# Trigger: this test must work on Windows runners where output may contain "runneradmin".
|
|
# Why: substring checks against command output can mistake path text for project names.
|
|
# Outcome: use config state for setup decisions, then validate behavior via CLI invocation.
|
|
if "main" not in config_manager.config.projects:
|
|
result = runner.invoke(cli_app, ["project", "add", "main", str(main_path), "--local"])
|
|
print(result.stdout)
|
|
assert result.exit_code == 0
|
|
|
|
# Confirm main is present
|
|
assert "main" in config_manager.config.projects
|
|
|
|
# Add a second project
|
|
result = runner.invoke(
|
|
cli_app, ["project", "add", "new_default", str(new_default_path), "--local"]
|
|
)
|
|
assert result.exit_code == 0
|
|
|
|
# Set new_default as default (if needed)
|
|
result = runner.invoke(cli_app, ["project", "default", "new_default", "--local"])
|
|
assert result.exit_code == 0
|
|
|
|
# Remove main
|
|
result = runner.invoke(cli_app, ["project", "remove", "main", "--local"])
|
|
if result.exit_code != 0:
|
|
print(f"STDOUT: {result.stdout}")
|
|
print(f"STDERR: {result.stderr}")
|
|
assert result.exit_code == 0
|
|
|
|
# Confirm only new_default exists and main does not
|
|
result = runner.invoke(cli_app, ["project", "list", "--local"], env=WIDE_TERMINAL_ENV)
|
|
assert result.exit_code == 0
|
|
config_after_list = config_manager.load_config()
|
|
assert "main" not in config_after_list.projects
|
|
assert "new_default" in config_after_list.projects
|