"""Tests for workspace CLI commands."""
import tempfile
from pathlib import Path
import pytest
from typer.testing import CliRunner
import basic_memory.config
from basic_memory.cli.app import app
from basic_memory.config import BasicMemoryConfig, ConfigManager
from basic_memory.schemas.cloud import WorkspaceInfo
# Importing the cloud package registers workspace_app on cloud_app.
import basic_memory.cli.commands.cloud as cloud_cmd # noqa: F401
import basic_memory.cli.commands.cloud.workspace as workspace_cmd # noqa: F401
@pytest.fixture
def runner():
return CliRunner()
def test_workspace_list_prints_available_workspaces(runner, monkeypatch):
async def fake_get_available_workspaces(context=None):
return [
WorkspaceInfo(
tenant_id="11111111-1111-1111-1111-111111111111",
workspace_type="personal",
name="Personal",
role="owner",
),
WorkspaceInfo(
tenant_id="22222222-2222-2222-2222-222222222222",
workspace_type="organization",
name="Team",
role="editor",
),
]
monkeypatch.setattr(workspace_cmd, "get_available_workspaces", fake_get_available_workspaces)
result = runner.invoke(app, ["cloud", "workspace", "list"])
assert result.exit_code == 0
assert "Available Workspaces" in result.stdout
assert "Personal" in result.stdout
assert "Team" in result.stdout
# Tenant ID may be truncated by Rich table rendering
assert "11111111" in result.stdout
def test_workspace_list_requires_oauth_login_message(runner, monkeypatch):
async def fail_get_available_workspaces(context=None): # pragma: no cover
raise RuntimeError("Workspace discovery requires OAuth login. Run 'bm cloud login' first.")
monkeypatch.setattr(workspace_cmd, "get_available_workspaces", fail_get_available_workspaces)
result = runner.invoke(app, ["cloud", "workspace", "list"])
assert result.exit_code == 1
assert "Workspace discovery requires OAuth login" in result.stdout
assert "bm cloud login" in result.stdout
class TestWorkspaceSetDefault:
"""Tests for 'bm cloud workspace set-default' command."""
@pytest.fixture(autouse=True)
def _setup_config(self, monkeypatch):
"""Set up a temp config for each test."""
self.temp_dir = tempfile.mkdtemp()
temp_path = Path(self.temp_dir)
config_dir = temp_path / ".basic-memory"
config_dir.mkdir(parents=True, exist_ok=True)
monkeypatch.setenv("HOME", str(temp_path))
monkeypatch.setenv("BASIC_MEMORY_CONFIG_DIR", str(config_dir))
basic_memory.config._CONFIG_CACHE = None
config_manager = ConfigManager()
test_config = BasicMemoryConfig(
projects={"main": {"path": str(temp_path / "main")}},
)
config_manager.save_config(test_config)
def test_set_default_workspace_by_name(self, runner, monkeypatch):
async def fake_get_available_workspaces(context=None):
return [
WorkspaceInfo(
tenant_id="11111111-1111-1111-1111-111111111111",
workspace_type="personal",
name="Personal",
role="owner",
),
]
monkeypatch.setattr(
workspace_cmd, "get_available_workspaces", fake_get_available_workspaces
)
result = runner.invoke(app, ["cloud", "workspace", "set-default", "Personal"])
assert result.exit_code == 0
assert "Default workspace set" in result.stdout
assert "Personal" in result.stdout
# Verify config was updated
basic_memory.config._CONFIG_CACHE = None
config = ConfigManager().config
assert config.default_workspace == "11111111-1111-1111-1111-111111111111"
def test_set_default_workspace_by_tenant_id(self, runner, monkeypatch):
async def fake_get_available_workspaces(context=None):
return [
WorkspaceInfo(
tenant_id="22222222-2222-2222-2222-222222222222",
workspace_type="organization",
name="Team",
role="editor",
),
]
monkeypatch.setattr(
workspace_cmd, "get_available_workspaces", fake_get_available_workspaces
)
result = runner.invoke(
app, ["cloud", "workspace", "set-default", "22222222-2222-2222-2222-222222222222"]
)
assert result.exit_code == 0
assert "Default workspace set" in result.stdout
def test_set_default_workspace_not_found(self, runner, monkeypatch):
async def fake_get_available_workspaces(context=None):
return [
WorkspaceInfo(
tenant_id="11111111-1111-1111-1111-111111111111",
workspace_type="personal",
name="Personal",
role="owner",
),
]
monkeypatch.setattr(
workspace_cmd, "get_available_workspaces", fake_get_available_workspaces
)
result = runner.invoke(app, ["cloud", "workspace", "set-default", "Nonexistent"])
assert result.exit_code == 1
assert "not found" in result.stdout
def test_set_default_workspace_no_workspaces(self, runner, monkeypatch):
async def fake_get_available_workspaces(context=None):
return []
monkeypatch.setattr(
workspace_cmd, "get_available_workspaces", fake_get_available_workspaces
)
result = runner.invoke(app, ["cloud", "workspace", "set-default", "Personal"])
assert result.exit_code == 1
assert "No accessible workspaces" in result.stdout
def test_set_default_workspace_oauth_error(self, runner, monkeypatch):
async def fail_get_available_workspaces(context=None): # pragma: no cover
raise RuntimeError(
"Workspace discovery requires OAuth login. Run 'bm cloud login' first."
)
monkeypatch.setattr(
workspace_cmd, "get_available_workspaces", fail_get_available_workspaces
)
result = runner.invoke(app, ["cloud", "workspace", "set-default", "Personal"])
assert result.exit_code == 1
assert "OAuth login" in result.stdout