Major additions: - Storage abstraction layer with filesystem and in-memory implementations - Gitea API integration with MCP tools for repository management - Console dialog mode with interactive command execution - WireGuard VPN DNS fix implementation and documentation - HTTP client streaming response support - Router generic result type - Parameter type validator for framework core Framework enhancements: - Console command registry improvements - Console dialog components - Method signature analyzer updates - Route mapper refinements - MCP server and tool mapper updates - Queue job chain and dependency commands - Discovery tokenizer improvements Infrastructure: - Deployment architecture documentation - Ansible playbook updates for WireGuard client regeneration - Production environment configuration updates - Docker Compose local configuration updates - Remove obsolete docker-compose.yml (replaced by environment-specific configs) Documentation: - PERMISSIONS.md for access control guidelines - WireGuard DNS fix implementation details - Console dialog mode usage guide - Deployment architecture overview Testing: - Multi-purpose attribute tests - Gitea Actions integration tests (typed and untyped)
93 lines
3.8 KiB
PHP
93 lines
3.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Framework\Console\ConsoleCommand;
|
|
use App\Framework\Core\ParameterTypeValidator;
|
|
use App\Framework\Examples\MultiPurposeAction;
|
|
use App\Framework\Mcp\McpTool;
|
|
use App\Framework\Reflection\WrappedReflectionMethod;
|
|
use App\Framework\Reflection\Cache\MethodCache;
|
|
use App\Framework\Core\ValueObjects\ClassName;
|
|
|
|
test('multi-purpose method has multiple attributes', function () {
|
|
$className = ClassName::create(MultiPurposeAction::class);
|
|
$methodName = 'listUsers';
|
|
|
|
// Create a mock method cache (simplified for testing)
|
|
$reflectionMethod = new \ReflectionMethod(MultiPurposeAction::class, $methodName);
|
|
$attributes = $reflectionMethod->getAttributes();
|
|
|
|
$attributeNames = array_map(fn($attr) => $attr->getName(), $attributes);
|
|
|
|
expect($attributeNames)->toContain(McpTool::class);
|
|
expect($attributeNames)->toContain(ConsoleCommand::class);
|
|
// Note: Route attribute checking would need Route class import
|
|
});
|
|
|
|
test('parameter type validator recognizes builtin types', function () {
|
|
$validator = new ParameterTypeValidator();
|
|
|
|
// Use reflection from actual method to test builtin types
|
|
$reflectionMethod = new \ReflectionMethod(MultiPurposeAction::class, 'listUsers');
|
|
$parameters = $reflectionMethod->getParameters();
|
|
|
|
// Test string parameter
|
|
$stringParam = $parameters[0]; // $status: string
|
|
expect($validator->isBuiltinType($stringParam->getType()))->toBeTrue();
|
|
|
|
// Test int parameter
|
|
$intParam = $parameters[1]; // $limit: int
|
|
expect($validator->isBuiltinType($intParam->getType()))->toBeTrue();
|
|
|
|
// Test bool parameter
|
|
$boolParam = $parameters[2]; // $includeDetails: bool
|
|
expect($validator->isBuiltinType($boolParam->getType()))->toBeTrue();
|
|
});
|
|
|
|
test('parameter type validator rejects non-builtin types', function () {
|
|
$validator = new ParameterTypeValidator();
|
|
|
|
// Use reflection from a method that has non-builtin types (if available)
|
|
// For now, test with a class that doesn't exist in our test
|
|
$reflectionClass = new \ReflectionClass(MultiPurposeAction::class);
|
|
|
|
// All methods in MultiPurposeAction should have only builtin types
|
|
// So we'll test with a known non-builtin type string
|
|
$classType = new \ReflectionClass(\stdClass::class);
|
|
$method = $classType->getMethod('__construct');
|
|
$parameters = $method->getParameters();
|
|
|
|
// If there are parameters, check they're not builtin (if they're object types)
|
|
if (count($parameters) > 0 && $parameters[0]->getType() instanceof \ReflectionNamedType) {
|
|
$typeName = $parameters[0]->getType()->getName();
|
|
if (! in_array($typeName, ['string', 'int', 'float', 'bool', 'array', 'mixed'], true)) {
|
|
expect($validator->isBuiltinType($parameters[0]->getType()))->toBeFalse();
|
|
}
|
|
}
|
|
});
|
|
|
|
test('multi-purpose method returns ActionResult', function () {
|
|
$action = new MultiPurposeAction();
|
|
|
|
$result = $action->listUsers('active', 10, false);
|
|
|
|
expect($result)->toBeInstanceOf(\App\Framework\Router\ActionResult::class);
|
|
expect($result)->toBeInstanceOf(\App\Framework\Router\Result\JsonResult::class);
|
|
});
|
|
|
|
test('ConsoleResult implements ActionResult', function () {
|
|
$textResult = new \App\Framework\Console\Result\TextResult('Test message');
|
|
|
|
expect($textResult)->toBeInstanceOf(\App\Framework\Router\ActionResult::class);
|
|
expect($textResult)->toBeInstanceOf(\App\Framework\Console\Result\ConsoleResult::class);
|
|
});
|
|
|
|
test('ToolResult implements ActionResult', function () {
|
|
$toolResult = \App\Framework\Mcp\Core\ValueObjects\ToolResult::success(['data' => 'test']);
|
|
|
|
expect($toolResult)->toBeInstanceOf(\App\Framework\Router\ActionResult::class);
|
|
expect($toolResult)->toBeInstanceOf(\App\Framework\Mcp\Core\ValueObjects\ToolResult::class);
|
|
});
|
|
|