Rename project from SmartTools to CmdForge
Major rename operation: - Rename Python package: smarttools -> cmdforge - Update CLI entry point: smarttools -> cmdforge - Update all imports and module references - Update pyproject.toml with new name, URLs, entry point - Update all HTML templates with new branding - Update documentation (CLAUDE.md, README.md, docs/*, wiki/*) - Update environment variables: - SMARTTOOLS_ENV -> CMDFORGE_ENV - SMARTTOOLS_REGISTRY_DB -> CMDFORGE_REGISTRY_DB - SMARTTOOLS_TOKEN -> CMDFORGE_TOKEN - SMARTTOOLS_REGISTRY_* -> CMDFORGE_REGISTRY_* - Update Dockerfile and docker-compose.yml - Update tests to use new package name - Update scripts and examples - Update package.json and tailwind.config.js All 158 unit tests pass. The CLI is working correctly with the new cmdforge command. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
+8
-8
@@ -1,8 +1,8 @@
|
||||
# SmartTools Test Suite
|
||||
# CmdForge Test Suite
|
||||
|
||||
## Overview
|
||||
|
||||
The test suite covers the core SmartTools modules with **158 unit tests** organized into four main test files:
|
||||
The test suite covers the core CmdForge modules with **158 unit tests** organized into four main test files:
|
||||
|
||||
| Test File | Module Tested | Test Count | Description |
|
||||
|-----------|---------------|------------|-------------|
|
||||
@@ -28,7 +28,7 @@ pytest tests/test_tool.py -v
|
||||
pytest tests/test_runner.py::TestSubstituteVariables -v
|
||||
|
||||
# Run with coverage
|
||||
pytest tests/ --cov=smarttools --cov-report=html
|
||||
pytest tests/ --cov=cmdforge --cov-report=html
|
||||
```
|
||||
|
||||
## Test Categories
|
||||
@@ -83,7 +83,7 @@ pytest tests/ --cov=smarttools --cov-report=html
|
||||
Run with a local registry server:
|
||||
```bash
|
||||
# Start registry server
|
||||
python -m smarttools.registry.app
|
||||
python -m cmdforge.registry.app
|
||||
|
||||
# Run integration tests
|
||||
pytest tests/test_registry_integration.py -v -m integration
|
||||
@@ -97,15 +97,15 @@ Common fixtures used across tests:
|
||||
@pytest.fixture
|
||||
def temp_tools_dir(tmp_path):
|
||||
"""Redirect TOOLS_DIR and BIN_DIR to temp directory."""
|
||||
with patch('smarttools.tool.TOOLS_DIR', tmp_path / ".smarttools"):
|
||||
with patch('smarttools.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
with patch('cmdforge.tool.TOOLS_DIR', tmp_path / ".cmdforge"):
|
||||
with patch('cmdforge.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
yield tmp_path
|
||||
|
||||
@pytest.fixture
|
||||
def temp_providers_file(tmp_path):
|
||||
"""Redirect providers.yaml to temp directory."""
|
||||
providers_file = tmp_path / ".smarttools" / "providers.yaml"
|
||||
with patch('smarttools.providers.PROVIDERS_FILE', providers_file):
|
||||
providers_file = tmp_path / ".cmdforge" / "providers.yaml"
|
||||
with patch('cmdforge.providers.PROVIDERS_FILE', providers_file):
|
||||
yield providers_file
|
||||
```
|
||||
|
||||
|
||||
+61
-61
@@ -7,8 +7,8 @@ from io import StringIO
|
||||
|
||||
import pytest
|
||||
|
||||
from smarttools.cli import main
|
||||
from smarttools.tool import Tool, ToolArgument, PromptStep
|
||||
from cmdforge.cli import main
|
||||
from cmdforge.tool import Tool, ToolArgument, PromptStep
|
||||
|
||||
|
||||
class TestCLIBasics:
|
||||
@@ -17,34 +17,34 @@ class TestCLIBasics:
|
||||
def test_help_flag(self, capsys):
|
||||
"""--help should show usage."""
|
||||
with pytest.raises(SystemExit) as exc_info:
|
||||
with patch('sys.argv', ['smarttools', '--help']):
|
||||
with patch('sys.argv', ['cmdforge', '--help']):
|
||||
main()
|
||||
|
||||
assert exc_info.value.code == 0
|
||||
captured = capsys.readouterr()
|
||||
assert 'usage' in captured.out.lower() or 'smarttools' in captured.out.lower()
|
||||
assert 'usage' in captured.out.lower() or 'cmdforge' in captured.out.lower()
|
||||
|
||||
def test_version_flag(self, capsys):
|
||||
"""--version should show version."""
|
||||
with pytest.raises(SystemExit) as exc_info:
|
||||
with patch('sys.argv', ['smarttools', '--version']):
|
||||
with patch('sys.argv', ['cmdforge', '--version']):
|
||||
main()
|
||||
|
||||
assert exc_info.value.code == 0
|
||||
|
||||
|
||||
class TestListCommand:
|
||||
"""Tests for 'smarttools list' command."""
|
||||
"""Tests for 'cmdforge list' command."""
|
||||
|
||||
@pytest.fixture
|
||||
def temp_tools_dir(self, tmp_path):
|
||||
with patch('smarttools.tool.TOOLS_DIR', tmp_path / ".smarttools"):
|
||||
with patch('smarttools.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
with patch('cmdforge.tool.TOOLS_DIR', tmp_path / ".cmdforge"):
|
||||
with patch('cmdforge.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
yield tmp_path
|
||||
|
||||
def test_list_empty(self, temp_tools_dir, capsys):
|
||||
"""List with no tools should show message."""
|
||||
with patch('sys.argv', ['smarttools', 'list']):
|
||||
with patch('sys.argv', ['cmdforge', 'list']):
|
||||
result = main()
|
||||
|
||||
assert result == 0
|
||||
@@ -53,12 +53,12 @@ class TestListCommand:
|
||||
|
||||
def test_list_with_tools(self, temp_tools_dir, capsys):
|
||||
"""List should show available tools."""
|
||||
from smarttools.tool import save_tool
|
||||
from cmdforge.tool import save_tool
|
||||
|
||||
save_tool(Tool(name="test-tool", description="A test tool"))
|
||||
save_tool(Tool(name="another-tool", description="Another tool"))
|
||||
|
||||
with patch('sys.argv', ['smarttools', 'list']):
|
||||
with patch('sys.argv', ['cmdforge', 'list']):
|
||||
result = main()
|
||||
|
||||
assert result == 0
|
||||
@@ -68,42 +68,42 @@ class TestListCommand:
|
||||
|
||||
|
||||
class TestCreateCommand:
|
||||
"""Tests for 'smarttools create' command."""
|
||||
"""Tests for 'cmdforge create' command."""
|
||||
|
||||
@pytest.fixture
|
||||
def temp_tools_dir(self, tmp_path):
|
||||
with patch('smarttools.tool.TOOLS_DIR', tmp_path / ".smarttools"):
|
||||
with patch('smarttools.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
with patch('cmdforge.tool.TOOLS_DIR', tmp_path / ".cmdforge"):
|
||||
with patch('cmdforge.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
yield tmp_path
|
||||
|
||||
def test_create_minimal(self, temp_tools_dir, capsys):
|
||||
"""Create a minimal tool."""
|
||||
with patch('sys.argv', ['smarttools', 'create', 'my-tool']):
|
||||
with patch('sys.argv', ['cmdforge', 'create', 'my-tool']):
|
||||
result = main()
|
||||
|
||||
assert result == 0
|
||||
|
||||
from smarttools.tool import tool_exists
|
||||
from cmdforge.tool import tool_exists
|
||||
assert tool_exists('my-tool')
|
||||
|
||||
def test_create_with_description(self, temp_tools_dir):
|
||||
"""Create tool with description."""
|
||||
with patch('sys.argv', ['smarttools', 'create', 'described-tool',
|
||||
with patch('sys.argv', ['cmdforge', 'create', 'described-tool',
|
||||
'-d', 'A helpful description']):
|
||||
result = main()
|
||||
|
||||
assert result == 0
|
||||
|
||||
from smarttools.tool import load_tool
|
||||
from cmdforge.tool import load_tool
|
||||
tool = load_tool('described-tool')
|
||||
assert tool.description == 'A helpful description'
|
||||
|
||||
def test_create_duplicate_fails(self, temp_tools_dir, capsys):
|
||||
"""Creating duplicate tool should fail."""
|
||||
from smarttools.tool import save_tool
|
||||
from cmdforge.tool import save_tool
|
||||
save_tool(Tool(name="existing"))
|
||||
|
||||
with patch('sys.argv', ['smarttools', 'create', 'existing']):
|
||||
with patch('sys.argv', ['cmdforge', 'create', 'existing']):
|
||||
result = main()
|
||||
|
||||
assert result != 0
|
||||
@@ -113,28 +113,28 @@ class TestCreateCommand:
|
||||
@pytest.mark.skip(reason="CLI does not yet validate tool names - potential enhancement")
|
||||
def test_create_invalid_name(self, temp_tools_dir, capsys):
|
||||
"""Invalid tool name should fail."""
|
||||
with patch('sys.argv', ['smarttools', 'create', 'invalid/name']):
|
||||
with patch('sys.argv', ['cmdforge', 'create', 'invalid/name']):
|
||||
result = main()
|
||||
|
||||
assert result != 0
|
||||
|
||||
|
||||
class TestDeleteCommand:
|
||||
"""Tests for 'smarttools delete' command."""
|
||||
"""Tests for 'cmdforge delete' command."""
|
||||
|
||||
@pytest.fixture
|
||||
def temp_tools_dir(self, tmp_path):
|
||||
with patch('smarttools.tool.TOOLS_DIR', tmp_path / ".smarttools"):
|
||||
with patch('smarttools.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
with patch('cmdforge.tool.TOOLS_DIR', tmp_path / ".cmdforge"):
|
||||
with patch('cmdforge.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
yield tmp_path
|
||||
|
||||
def test_delete_existing(self, temp_tools_dir, capsys):
|
||||
"""Delete an existing tool."""
|
||||
from smarttools.tool import save_tool, tool_exists
|
||||
from cmdforge.tool import save_tool, tool_exists
|
||||
save_tool(Tool(name="to-delete"))
|
||||
assert tool_exists("to-delete")
|
||||
|
||||
with patch('sys.argv', ['smarttools', 'delete', 'to-delete', '-f']):
|
||||
with patch('sys.argv', ['cmdforge', 'delete', 'to-delete', '-f']):
|
||||
result = main()
|
||||
|
||||
assert result == 0
|
||||
@@ -142,24 +142,24 @@ class TestDeleteCommand:
|
||||
|
||||
def test_delete_nonexistent(self, temp_tools_dir, capsys):
|
||||
"""Deleting nonexistent tool should fail."""
|
||||
with patch('sys.argv', ['smarttools', 'delete', 'nonexistent', '-f']):
|
||||
with patch('sys.argv', ['cmdforge', 'delete', 'nonexistent', '-f']):
|
||||
result = main()
|
||||
|
||||
assert result != 0
|
||||
|
||||
|
||||
class TestRunCommand:
|
||||
"""Tests for 'smarttools run' command."""
|
||||
"""Tests for 'cmdforge run' command."""
|
||||
|
||||
@pytest.fixture
|
||||
def temp_tools_dir(self, tmp_path):
|
||||
with patch('smarttools.tool.TOOLS_DIR', tmp_path / ".smarttools"):
|
||||
with patch('smarttools.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
with patch('cmdforge.tool.TOOLS_DIR', tmp_path / ".cmdforge"):
|
||||
with patch('cmdforge.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
yield tmp_path
|
||||
|
||||
def test_run_simple_tool(self, temp_tools_dir, capsys):
|
||||
"""Run a simple tool without AI calls."""
|
||||
from smarttools.tool import save_tool
|
||||
from cmdforge.tool import save_tool
|
||||
|
||||
tool = Tool(
|
||||
name="echo",
|
||||
@@ -167,7 +167,7 @@ class TestRunCommand:
|
||||
)
|
||||
save_tool(tool)
|
||||
|
||||
with patch('sys.argv', ['smarttools', 'run', 'echo']):
|
||||
with patch('sys.argv', ['cmdforge', 'run', 'echo']):
|
||||
with patch('sys.stdin', StringIO("Hello")):
|
||||
with patch('sys.stdin.isatty', return_value=False):
|
||||
result = main()
|
||||
@@ -178,7 +178,7 @@ class TestRunCommand:
|
||||
|
||||
def test_run_with_mock_provider(self, temp_tools_dir, capsys):
|
||||
"""Run tool with mock provider."""
|
||||
from smarttools.tool import save_tool
|
||||
from cmdforge.tool import save_tool
|
||||
|
||||
tool = Tool(
|
||||
name="summarize",
|
||||
@@ -189,7 +189,7 @@ class TestRunCommand:
|
||||
)
|
||||
save_tool(tool)
|
||||
|
||||
with patch('sys.argv', ['smarttools', 'run', 'summarize']):
|
||||
with patch('sys.argv', ['cmdforge', 'run', 'summarize']):
|
||||
with patch('sys.stdin', StringIO("Some text")):
|
||||
with patch('sys.stdin.isatty', return_value=False):
|
||||
result = main()
|
||||
@@ -200,24 +200,24 @@ class TestRunCommand:
|
||||
|
||||
def test_run_nonexistent_tool(self, temp_tools_dir, capsys):
|
||||
"""Running nonexistent tool should fail."""
|
||||
with patch('sys.argv', ['smarttools', 'run', 'nonexistent']):
|
||||
with patch('sys.argv', ['cmdforge', 'run', 'nonexistent']):
|
||||
result = main()
|
||||
|
||||
assert result != 0
|
||||
|
||||
|
||||
class TestTestCommand:
|
||||
"""Tests for 'smarttools test' command."""
|
||||
"""Tests for 'cmdforge test' command."""
|
||||
|
||||
@pytest.fixture
|
||||
def temp_tools_dir(self, tmp_path):
|
||||
with patch('smarttools.tool.TOOLS_DIR', tmp_path / ".smarttools"):
|
||||
with patch('smarttools.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
with patch('cmdforge.tool.TOOLS_DIR', tmp_path / ".cmdforge"):
|
||||
with patch('cmdforge.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
yield tmp_path
|
||||
|
||||
def test_test_tool(self, temp_tools_dir, capsys):
|
||||
"""Test command should run with mock provider."""
|
||||
from smarttools.tool import save_tool
|
||||
from cmdforge.tool import save_tool
|
||||
|
||||
tool = Tool(
|
||||
name="test-me",
|
||||
@@ -229,7 +229,7 @@ class TestTestCommand:
|
||||
save_tool(tool)
|
||||
|
||||
# Provide stdin input for the test command
|
||||
with patch('sys.argv', ['smarttools', 'test', 'test-me']):
|
||||
with patch('sys.argv', ['cmdforge', 'test', 'test-me']):
|
||||
with patch('sys.stdin', StringIO("test input")):
|
||||
result = main()
|
||||
|
||||
@@ -240,17 +240,17 @@ class TestTestCommand:
|
||||
|
||||
|
||||
class TestProvidersCommand:
|
||||
"""Tests for 'smarttools providers' command."""
|
||||
"""Tests for 'cmdforge providers' command."""
|
||||
|
||||
@pytest.fixture
|
||||
def temp_providers_file(self, tmp_path):
|
||||
providers_file = tmp_path / ".smarttools" / "providers.yaml"
|
||||
with patch('smarttools.providers.PROVIDERS_FILE', providers_file):
|
||||
providers_file = tmp_path / ".cmdforge" / "providers.yaml"
|
||||
with patch('cmdforge.providers.PROVIDERS_FILE', providers_file):
|
||||
yield providers_file
|
||||
|
||||
def test_providers_list(self, temp_providers_file, capsys):
|
||||
"""List providers."""
|
||||
with patch('sys.argv', ['smarttools', 'providers']):
|
||||
with patch('sys.argv', ['cmdforge', 'providers']):
|
||||
result = main()
|
||||
|
||||
assert result == 0
|
||||
@@ -260,47 +260,47 @@ class TestProvidersCommand:
|
||||
|
||||
def test_providers_add(self, temp_providers_file, capsys):
|
||||
"""Add a custom provider."""
|
||||
with patch('sys.argv', ['smarttools', 'providers', 'add',
|
||||
with patch('sys.argv', ['cmdforge', 'providers', 'add',
|
||||
'custom', 'my-ai --prompt']):
|
||||
result = main()
|
||||
|
||||
assert result == 0
|
||||
|
||||
from smarttools.providers import get_provider
|
||||
from cmdforge.providers import get_provider
|
||||
provider = get_provider('custom')
|
||||
assert provider is not None
|
||||
assert provider.command == 'my-ai --prompt'
|
||||
|
||||
def test_providers_remove(self, temp_providers_file, capsys):
|
||||
"""Remove a provider."""
|
||||
from smarttools.providers import add_provider, Provider
|
||||
from cmdforge.providers import add_provider, Provider
|
||||
add_provider(Provider('removeme', 'cmd'))
|
||||
|
||||
with patch('sys.argv', ['smarttools', 'providers', 'remove', 'removeme']):
|
||||
with patch('sys.argv', ['cmdforge', 'providers', 'remove', 'removeme']):
|
||||
result = main()
|
||||
|
||||
assert result == 0
|
||||
|
||||
from smarttools.providers import get_provider
|
||||
from cmdforge.providers import get_provider
|
||||
assert get_provider('removeme') is None
|
||||
|
||||
|
||||
class TestRefreshCommand:
|
||||
"""Tests for 'smarttools refresh' command."""
|
||||
"""Tests for 'cmdforge refresh' command."""
|
||||
|
||||
@pytest.fixture
|
||||
def temp_tools_dir(self, tmp_path):
|
||||
with patch('smarttools.tool.TOOLS_DIR', tmp_path / ".smarttools"):
|
||||
with patch('smarttools.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
with patch('cmdforge.tool.TOOLS_DIR', tmp_path / ".cmdforge"):
|
||||
with patch('cmdforge.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
yield tmp_path
|
||||
|
||||
def test_refresh_creates_wrappers(self, temp_tools_dir, capsys):
|
||||
"""Refresh should create wrapper scripts."""
|
||||
from smarttools.tool import save_tool, get_bin_dir
|
||||
from cmdforge.tool import save_tool, get_bin_dir
|
||||
|
||||
save_tool(Tool(name="wrapper-test"))
|
||||
|
||||
with patch('sys.argv', ['smarttools', 'refresh']):
|
||||
with patch('sys.argv', ['cmdforge', 'refresh']):
|
||||
result = main()
|
||||
|
||||
assert result == 0
|
||||
@@ -310,17 +310,17 @@ class TestRefreshCommand:
|
||||
|
||||
|
||||
class TestDocsCommand:
|
||||
"""Tests for 'smarttools docs' command."""
|
||||
"""Tests for 'cmdforge docs' command."""
|
||||
|
||||
@pytest.fixture
|
||||
def temp_tools_dir(self, tmp_path):
|
||||
with patch('smarttools.tool.TOOLS_DIR', tmp_path / ".smarttools"):
|
||||
with patch('smarttools.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
with patch('cmdforge.tool.TOOLS_DIR', tmp_path / ".cmdforge"):
|
||||
with patch('cmdforge.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
yield tmp_path
|
||||
|
||||
def test_docs_for_tool_with_readme(self, temp_tools_dir, capsys):
|
||||
"""Docs should show README content when it exists."""
|
||||
from smarttools.tool import save_tool, get_tools_dir
|
||||
from cmdforge.tool import save_tool, get_tools_dir
|
||||
|
||||
tool = Tool(
|
||||
name="documented",
|
||||
@@ -332,7 +332,7 @@ class TestDocsCommand:
|
||||
readme_path = get_tools_dir() / "documented" / "README.md"
|
||||
readme_path.write_text("# Documented Tool\n\nThis is the documentation.")
|
||||
|
||||
with patch('sys.argv', ['smarttools', 'docs', 'documented']):
|
||||
with patch('sys.argv', ['cmdforge', 'docs', 'documented']):
|
||||
result = main()
|
||||
|
||||
assert result == 0
|
||||
@@ -342,12 +342,12 @@ class TestDocsCommand:
|
||||
|
||||
def test_docs_no_readme(self, temp_tools_dir, capsys):
|
||||
"""Docs without README should prompt to create one."""
|
||||
from smarttools.tool import save_tool
|
||||
from cmdforge.tool import save_tool
|
||||
|
||||
tool = Tool(name="no-docs")
|
||||
save_tool(tool)
|
||||
|
||||
with patch('sys.argv', ['smarttools', 'docs', 'no-docs']):
|
||||
with patch('sys.argv', ['cmdforge', 'docs', 'no-docs']):
|
||||
result = main()
|
||||
|
||||
assert result == 1 # Returns 1 when no README
|
||||
|
||||
@@ -7,7 +7,7 @@ from unittest.mock import patch, MagicMock
|
||||
import pytest
|
||||
import yaml
|
||||
|
||||
from smarttools.providers import (
|
||||
from cmdforge.providers import (
|
||||
Provider, ProviderResult,
|
||||
load_providers, save_providers, get_provider,
|
||||
add_provider, delete_provider,
|
||||
@@ -122,8 +122,8 @@ class TestProviderPersistence:
|
||||
@pytest.fixture
|
||||
def temp_providers_file(self, tmp_path):
|
||||
"""Create a temporary providers file."""
|
||||
providers_file = tmp_path / ".smarttools" / "providers.yaml"
|
||||
with patch('smarttools.providers.PROVIDERS_FILE', providers_file):
|
||||
providers_file = tmp_path / ".cmdforge" / "providers.yaml"
|
||||
with patch('cmdforge.providers.PROVIDERS_FILE', providers_file):
|
||||
yield providers_file
|
||||
|
||||
def test_save_and_load_providers(self, temp_providers_file):
|
||||
@@ -220,8 +220,8 @@ class TestCallProvider:
|
||||
@pytest.fixture
|
||||
def temp_providers_file(self, tmp_path):
|
||||
"""Create a temporary providers file."""
|
||||
providers_file = tmp_path / ".smarttools" / "providers.yaml"
|
||||
with patch('smarttools.providers.PROVIDERS_FILE', providers_file):
|
||||
providers_file = tmp_path / ".cmdforge" / "providers.yaml"
|
||||
with patch('cmdforge.providers.PROVIDERS_FILE', providers_file):
|
||||
yield providers_file
|
||||
|
||||
def test_call_mock_provider(self, temp_providers_file):
|
||||
@@ -342,8 +342,8 @@ class TestProviderCommandParsing:
|
||||
|
||||
@pytest.fixture
|
||||
def temp_providers_file(self, tmp_path):
|
||||
providers_file = tmp_path / ".smarttools" / "providers.yaml"
|
||||
with patch('smarttools.providers.PROVIDERS_FILE', providers_file):
|
||||
providers_file = tmp_path / ".cmdforge" / "providers.yaml"
|
||||
with patch('cmdforge.providers.PROVIDERS_FILE', providers_file):
|
||||
yield providers_file
|
||||
|
||||
@patch('shutil.which')
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"""Integration tests for SmartTools Registry.
|
||||
"""Integration tests for CmdForge Registry.
|
||||
|
||||
These tests verify the CLI and server work together correctly.
|
||||
Run with: pytest tests/test_registry_integration.py -v
|
||||
|
||||
Note: These tests require the registry server to be running locally:
|
||||
python -m smarttools.registry.app
|
||||
python -m cmdforge.registry.app
|
||||
"""
|
||||
|
||||
import json
|
||||
@@ -18,17 +18,17 @@ import pytest
|
||||
import yaml
|
||||
|
||||
# Test without requiring server for unit tests
|
||||
from smarttools.config import Config, RegistryConfig, load_config, save_config
|
||||
from smarttools.manifest import (
|
||||
from cmdforge.config import Config, RegistryConfig, load_config, save_config
|
||||
from cmdforge.manifest import (
|
||||
Manifest, Dependency, ToolOverride,
|
||||
load_manifest, save_manifest, create_manifest,
|
||||
parse_version_constraint
|
||||
)
|
||||
from smarttools.resolver import (
|
||||
from cmdforge.resolver import (
|
||||
ToolSpec, ToolResolver, ResolvedTool,
|
||||
resolve_tool, find_tool, list_installed_tools
|
||||
)
|
||||
from smarttools.registry_client import (
|
||||
from cmdforge.registry_client import (
|
||||
RegistryClient, RegistryError, PaginatedResponse,
|
||||
ToolInfo, DownloadResult
|
||||
)
|
||||
@@ -238,7 +238,7 @@ class TestToolResolver:
|
||||
def test_deterministic_owner_order(self, tmp_path):
|
||||
"""Test that official namespace is preferred over others."""
|
||||
# Create fake tool directories
|
||||
tools_dir = tmp_path / ".smarttools"
|
||||
tools_dir = tmp_path / ".cmdforge"
|
||||
|
||||
# Create alice/mytool
|
||||
alice_tool = tools_dir / "alice" / "mytool"
|
||||
|
||||
+12
-12
@@ -3,15 +3,15 @@
|
||||
import pytest
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
from smarttools.runner import (
|
||||
from cmdforge.runner import (
|
||||
substitute_variables,
|
||||
execute_prompt_step,
|
||||
execute_code_step,
|
||||
run_tool,
|
||||
create_argument_parser
|
||||
)
|
||||
from smarttools.tool import Tool, ToolArgument, PromptStep, CodeStep
|
||||
from smarttools.providers import ProviderResult
|
||||
from cmdforge.tool import Tool, ToolArgument, PromptStep, CodeStep
|
||||
from cmdforge.providers import ProviderResult
|
||||
|
||||
|
||||
class TestSubstituteVariables:
|
||||
@@ -96,7 +96,7 @@ Line 3: {var1} again"""
|
||||
class TestExecutePromptStep:
|
||||
"""Tests for prompt step execution."""
|
||||
|
||||
@patch('smarttools.runner.call_provider')
|
||||
@patch('cmdforge.runner.call_provider')
|
||||
def test_successful_prompt(self, mock_call):
|
||||
mock_call.return_value = ProviderResult(
|
||||
text="This is the response",
|
||||
@@ -119,7 +119,7 @@ class TestExecutePromptStep:
|
||||
call_args = mock_call.call_args
|
||||
assert "Some text to summarize" in call_args[0][1]
|
||||
|
||||
@patch('smarttools.runner.call_provider')
|
||||
@patch('cmdforge.runner.call_provider')
|
||||
def test_failed_prompt(self, mock_call):
|
||||
mock_call.return_value = ProviderResult(
|
||||
text="",
|
||||
@@ -133,7 +133,7 @@ class TestExecutePromptStep:
|
||||
assert success is False
|
||||
assert output == ""
|
||||
|
||||
@patch('smarttools.runner.mock_provider')
|
||||
@patch('cmdforge.runner.mock_provider')
|
||||
def test_mock_provider_used(self, mock_mock):
|
||||
mock_mock.return_value = ProviderResult(text="mock response", success=True)
|
||||
|
||||
@@ -143,7 +143,7 @@ class TestExecutePromptStep:
|
||||
assert success is True
|
||||
mock_mock.assert_called_once()
|
||||
|
||||
@patch('smarttools.runner.call_provider')
|
||||
@patch('cmdforge.runner.call_provider')
|
||||
def test_provider_override(self, mock_call):
|
||||
mock_call.return_value = ProviderResult(text="response", success=True)
|
||||
|
||||
@@ -277,7 +277,7 @@ class TestRunTool:
|
||||
output, exit_code = run_tool(tool, "", {"name": "Alice"})
|
||||
assert output == "Hello, Alice!"
|
||||
|
||||
@patch('smarttools.runner.call_provider')
|
||||
@patch('cmdforge.runner.call_provider')
|
||||
def test_tool_with_prompt_step(self, mock_call):
|
||||
mock_call.return_value = ProviderResult(text="Summarized!", success=True)
|
||||
|
||||
@@ -315,7 +315,7 @@ class TestRunTool:
|
||||
assert exit_code == 0
|
||||
assert output == "Words: 4"
|
||||
|
||||
@patch('smarttools.runner.call_provider')
|
||||
@patch('cmdforge.runner.call_provider')
|
||||
def test_tool_with_multiple_steps(self, mock_call):
|
||||
mock_call.return_value = ProviderResult(text="AI response", success=True)
|
||||
|
||||
@@ -334,7 +334,7 @@ class TestRunTool:
|
||||
assert exit_code == 0
|
||||
assert "Result: AI response" in output
|
||||
|
||||
@patch('smarttools.runner.call_provider')
|
||||
@patch('cmdforge.runner.call_provider')
|
||||
def test_tool_dry_run(self, mock_call):
|
||||
tool = Tool(
|
||||
name="test",
|
||||
@@ -351,7 +351,7 @@ class TestRunTool:
|
||||
assert exit_code == 0
|
||||
assert "DRY RUN" in output
|
||||
|
||||
@patch('smarttools.runner.call_provider')
|
||||
@patch('cmdforge.runner.call_provider')
|
||||
def test_tool_provider_override(self, mock_call):
|
||||
mock_call.return_value = ProviderResult(text="response", success=True)
|
||||
|
||||
@@ -368,7 +368,7 @@ class TestRunTool:
|
||||
# Should use override
|
||||
assert mock_call.call_args[0][0] == "gpt4"
|
||||
|
||||
@patch('smarttools.runner.call_provider')
|
||||
@patch('cmdforge.runner.call_provider')
|
||||
def test_tool_prompt_failure(self, mock_call):
|
||||
mock_call.return_value = ProviderResult(text="", success=False, error="API error")
|
||||
|
||||
|
||||
+8
-8
@@ -7,7 +7,7 @@ from unittest.mock import patch
|
||||
import pytest
|
||||
import yaml
|
||||
|
||||
from smarttools.tool import (
|
||||
from cmdforge.tool import (
|
||||
Tool, ToolArgument, PromptStep, CodeStep,
|
||||
validate_tool_name, load_tool, save_tool, delete_tool,
|
||||
list_tools, tool_exists, create_wrapper_script,
|
||||
@@ -390,8 +390,8 @@ class TestToolPersistence:
|
||||
@pytest.fixture
|
||||
def temp_tools_dir(self, tmp_path):
|
||||
"""Create a temporary tools directory."""
|
||||
with patch('smarttools.tool.TOOLS_DIR', tmp_path / ".smarttools"):
|
||||
with patch('smarttools.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
with patch('cmdforge.tool.TOOLS_DIR', tmp_path / ".cmdforge"):
|
||||
with patch('cmdforge.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
yield tmp_path
|
||||
|
||||
def test_save_and_load_tool(self, temp_tools_dir):
|
||||
@@ -457,14 +457,14 @@ class TestToolPersistence:
|
||||
def test_create_wrapper_script(self, temp_tools_dir):
|
||||
save_tool(Tool(name="wrapper-test"))
|
||||
|
||||
from smarttools.tool import get_bin_dir
|
||||
from cmdforge.tool import get_bin_dir
|
||||
wrapper_path = get_bin_dir() / "wrapper-test"
|
||||
|
||||
assert wrapper_path.exists()
|
||||
content = wrapper_path.read_text()
|
||||
assert "#!/bin/bash" in content
|
||||
assert "wrapper-test" in content
|
||||
assert "smarttools.runner" in content
|
||||
assert "cmdforge.runner" in content
|
||||
|
||||
|
||||
class TestLegacyFormat:
|
||||
@@ -473,9 +473,9 @@ class TestLegacyFormat:
|
||||
@pytest.fixture
|
||||
def temp_tools_dir(self, tmp_path):
|
||||
"""Create a temporary tools directory."""
|
||||
with patch('smarttools.tool.TOOLS_DIR', tmp_path / ".smarttools"):
|
||||
with patch('smarttools.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
yield tmp_path / ".smarttools"
|
||||
with patch('cmdforge.tool.TOOLS_DIR', tmp_path / ".cmdforge"):
|
||||
with patch('cmdforge.tool.BIN_DIR', tmp_path / ".local" / "bin"):
|
||||
yield tmp_path / ".cmdforge"
|
||||
|
||||
def test_load_legacy_format(self, temp_tools_dir):
|
||||
"""Test loading a tool in the old format."""
|
||||
|
||||
Reference in New Issue
Block a user