135 lines
4.4 KiB
Python
135 lines
4.4 KiB
Python
import os
|
|
import shutil
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
from typer.testing import CliRunner
|
|
|
|
from nanobot.cli.commands import app
|
|
|
|
runner = CliRunner()
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_paths():
|
|
"""Mock configuration and workspace paths for isolation."""
|
|
with patch("nanobot.config.loader.get_config_path") as mock_config_path, \
|
|
patch("nanobot.config.loader.save_config") as mock_save_config, \
|
|
patch("nanobot.utils.helpers.get_workspace_path") as mock_ws_path:
|
|
|
|
# Create temporary paths
|
|
base_dir = Path("./test_onboard_data")
|
|
if base_dir.exists():
|
|
shutil.rmtree(base_dir)
|
|
base_dir.mkdir()
|
|
|
|
config_file = base_dir / "config.json"
|
|
workspace_dir = base_dir / "workspace"
|
|
|
|
mock_config_path.return_value = config_file
|
|
mock_ws_path.return_value = workspace_dir
|
|
|
|
# We need save_config to actually write the file for existence checks to work
|
|
def side_effect_save_config(config):
|
|
with open(config_file, "w") as f:
|
|
f.write("{}")
|
|
|
|
mock_save_config.side_effect = side_effect_save_config
|
|
|
|
yield config_file, workspace_dir
|
|
|
|
# Cleanup
|
|
if base_dir.exists():
|
|
shutil.rmtree(base_dir)
|
|
|
|
|
|
def test_onboard_fresh_install(mock_paths):
|
|
"""Test onboarding with no existing files."""
|
|
config_file, workspace_dir = mock_paths
|
|
|
|
result = runner.invoke(app, ["onboard"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "Created config" in result.stdout
|
|
assert "Created workspace" in result.stdout
|
|
assert "nanobot is ready" in result.stdout
|
|
|
|
assert config_file.exists()
|
|
assert workspace_dir.exists()
|
|
assert (workspace_dir / "AGENTS.md").exists()
|
|
assert (workspace_dir / "memory" / "MEMORY.md").exists()
|
|
|
|
|
|
def test_onboard_existing_config_no_overwrite(mock_paths):
|
|
"""Test onboarding with existing config, user declines overwrite."""
|
|
config_file, workspace_dir = mock_paths
|
|
|
|
# Pre-create config
|
|
config_file.write_text('{"existing": true}')
|
|
|
|
# Input "n" for overwrite prompt
|
|
result = runner.invoke(app, ["onboard"], input="n\n")
|
|
|
|
assert result.exit_code == 0
|
|
assert "Config already exists" in result.stdout
|
|
|
|
# Verify config was NOT changed
|
|
assert '{"existing": true}' in config_file.read_text()
|
|
|
|
# Verify workspace was still created
|
|
assert "Created workspace" in result.stdout
|
|
assert workspace_dir.exists()
|
|
assert (workspace_dir / "AGENTS.md").exists()
|
|
|
|
|
|
def test_onboard_existing_config_overwrite(mock_paths):
|
|
"""Test onboarding with existing config, user checks overwrite."""
|
|
config_file, workspace_dir = mock_paths
|
|
|
|
# Pre-create config
|
|
config_file.write_text('{"existing": true}')
|
|
|
|
# Input "y" for overwrite prompt
|
|
result = runner.invoke(app, ["onboard"], input="y\n")
|
|
|
|
assert result.exit_code == 0
|
|
assert "Config already exists" in result.stdout
|
|
assert "Created config" in result.stdout
|
|
|
|
# Verify config WAS changed (our mock writes "{}")
|
|
test_content = config_file.read_text()
|
|
assert test_content == "{}" or test_content == ""
|
|
|
|
assert workspace_dir.exists()
|
|
|
|
|
|
def test_onboard_existing_workspace_safe_create(mock_paths):
|
|
"""Test onboarding with existing workspace safely creates templates without prompting."""
|
|
config_file, workspace_dir = mock_paths
|
|
|
|
# Pre-create workspace
|
|
workspace_dir.mkdir(parents=True)
|
|
|
|
# Scenario: Config exists (keep it), Workspace exists (add templates automatically)
|
|
config_file.write_text("{}")
|
|
|
|
inputs = "n\n" # No overwrite config
|
|
result = runner.invoke(app, ["onboard"], input=inputs)
|
|
|
|
assert result.exit_code == 0
|
|
# Workspace exists message
|
|
# Depending on implementation, it might say "Workspace already exists" or just proceed.
|
|
# Code in commands.py Line 180: if not workspace.exists(): ...
|
|
# It does NOT print "Workspace already exists" if it exists.
|
|
# It only prints "Created workspace" if it created it.
|
|
|
|
assert "Created workspace" not in result.stdout
|
|
|
|
# Should NOT prompt for templates
|
|
assert "Create missing default templates?" not in result.stdout
|
|
|
|
# But SHOULD create them (since _create_workspace_templates is called unconditionally)
|
|
assert "Created AGENTS.md" in result.stdout
|
|
assert (workspace_dir / "AGENTS.md").exists()
|