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); });