Some checks failed
Deploy Application / deploy (push) Has been cancelled
164 lines
5.5 KiB
PHP
164 lines
5.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Unit\Framework\LiveComponents\Security;
|
|
|
|
require_once __DIR__ . '/TestComponents.php';
|
|
|
|
use App\Application\LiveComponents\Counter\CounterState;
|
|
use App\Framework\Attributes\Execution\AttributeExecutionContext;
|
|
use App\Framework\Core\ValueObjects\ClassName;
|
|
use App\Framework\Core\ValueObjects\MethodName;
|
|
use App\Framework\DI\DefaultContainer;
|
|
use App\Framework\LiveComponents\Attributes\Action;
|
|
use App\Framework\LiveComponents\Contracts\LiveComponentContract;
|
|
use App\Framework\LiveComponents\Security\ActionValidator;
|
|
use App\Framework\LiveComponents\Security\LiveComponentContextHelper;
|
|
use App\Framework\LiveComponents\ValueObjects\ActionParameters;
|
|
use App\Framework\LiveComponents\ValueObjects\ComponentId;
|
|
use Tests\Unit\Framework\LiveComponents\Security\ArrayReturnTypeComponent;
|
|
use Tests\Unit\Framework\LiveComponents\Security\PrimitiveReturnTypeComponent;
|
|
use Tests\Unit\Framework\LiveComponents\Security\PrivateActionComponent;
|
|
use Tests\Unit\Framework\LiveComponents\Security\StaticActionComponent;
|
|
use Tests\Unit\Framework\LiveComponents\Security\ValidActionComponent;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
final class ActionValidatorTest extends TestCase
|
|
{
|
|
private ActionValidator $validator;
|
|
private DefaultContainer $container;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
$this->container = new DefaultContainer();
|
|
$this->validator = new ActionValidator();
|
|
}
|
|
|
|
public function test_validates_valid_action(): void
|
|
{
|
|
$component = $this->createValidComponent();
|
|
$context = $this->createContext($component, 'validAction');
|
|
$actionAttribute = new Action();
|
|
|
|
// Should not throw
|
|
$this->validator->validate($context, $actionAttribute);
|
|
$this->assertTrue(true);
|
|
}
|
|
|
|
public function test_rejects_reserved_method(): void
|
|
{
|
|
$component = $this->createValidComponent();
|
|
$context = $this->createContext($component, 'onMount');
|
|
$actionAttribute = new Action();
|
|
|
|
$this->expectException(\BadMethodCallException::class);
|
|
$this->expectExceptionMessage('reserved method');
|
|
|
|
$this->validator->validate($context, $actionAttribute);
|
|
}
|
|
|
|
public function test_rejects_non_existent_method(): void
|
|
{
|
|
$component = $this->createValidComponent();
|
|
$context = $this->createContext($component, 'nonExistentMethod');
|
|
$actionAttribute = new Action();
|
|
|
|
$this->expectException(\BadMethodCallException::class);
|
|
$this->expectExceptionMessage('not found');
|
|
|
|
$this->validator->validate($context, $actionAttribute);
|
|
}
|
|
|
|
public function test_rejects_private_method(): void
|
|
{
|
|
$component = new PrivateActionComponent(
|
|
ComponentId::create('test', 'demo'),
|
|
CounterState::empty()
|
|
);
|
|
|
|
$context = $this->createContext($component, 'privateAction');
|
|
$actionAttribute = new Action();
|
|
|
|
$this->expectException(\BadMethodCallException::class);
|
|
$this->expectExceptionMessage('must be public');
|
|
|
|
$this->validator->validate($context, $actionAttribute);
|
|
}
|
|
|
|
public function test_rejects_static_method(): void
|
|
{
|
|
$component = new StaticActionComponent(
|
|
ComponentId::create('test', 'demo'),
|
|
CounterState::empty()
|
|
);
|
|
|
|
$context = $this->createContext($component, 'staticAction');
|
|
$actionAttribute = new Action();
|
|
|
|
$this->expectException(\BadMethodCallException::class);
|
|
$this->expectExceptionMessage('cannot be static');
|
|
|
|
$this->validator->validate($context, $actionAttribute);
|
|
}
|
|
|
|
public function test_rejects_primitive_return_type(): void
|
|
{
|
|
$component = new PrimitiveReturnTypeComponent(
|
|
ComponentId::create('test', 'demo'),
|
|
CounterState::empty()
|
|
);
|
|
|
|
$context = $this->createContext($component, 'intAction');
|
|
$actionAttribute = new Action();
|
|
|
|
$this->expectException(\BadMethodCallException::class);
|
|
$this->expectExceptionMessage('must return a State object');
|
|
|
|
$this->validator->validate($context, $actionAttribute);
|
|
}
|
|
|
|
public function test_rejects_array_return_type(): void
|
|
{
|
|
$component = new ArrayReturnTypeComponent(
|
|
ComponentId::create('test', 'demo'),
|
|
CounterState::empty()
|
|
);
|
|
|
|
$context = $this->createContext($component, 'arrayAction');
|
|
$actionAttribute = new Action();
|
|
|
|
$this->expectException(\BadMethodCallException::class);
|
|
$this->expectExceptionMessage('must return a State object');
|
|
|
|
$this->validator->validate($context, $actionAttribute);
|
|
}
|
|
|
|
private function createValidComponent(): LiveComponentContract
|
|
{
|
|
return new ValidActionComponent(
|
|
ComponentId::create('test', 'demo'),
|
|
CounterState::empty()
|
|
);
|
|
}
|
|
|
|
private function createContext(LiveComponentContract $component, string $methodName): AttributeExecutionContext
|
|
{
|
|
$componentClass = ClassName::create($component::class);
|
|
$method = MethodName::create($methodName);
|
|
$componentId = $component->id;
|
|
$actionParameters = ActionParameters::fromArray([]);
|
|
|
|
return LiveComponentContextHelper::createForAction(
|
|
container: $this->container,
|
|
componentClass: $componentClass,
|
|
actionMethod: $method,
|
|
componentId: $componentId,
|
|
actionParameters: $actionParameters,
|
|
component: $component
|
|
);
|
|
}
|
|
}
|
|
|