Files
WP-LIT-MCP/tests/Unit/Integrations/Divi/Release/DiviToolGateTest.php
T
2026-09-30 01:54:36 +02:00

107 lines
4.2 KiB
PHP

<?php
declare(strict_types=1);
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
use LIT\MCP\Abilities\Ability;
use LIT\MCP\Integrations\Divi\Release\DiviToolGate;
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
use LIT\MCP\Tests\Support\FakeChangeLog;
use LIT\MCP\Tests\Unit\TestCase;
use Mockery;
use WP_Error;
final class DiviToolGateTest extends TestCase
{
private const GROUPS = [
'lit/divi-insert' => 'divi',
'lit/divi-outline' => 'divi',
'lit/library-save' => 'divi-library',
'lit/tb-create-template' => 'divi-theme-builder',
'lit/content-create' => 'wordpress',
];
private function ability(string $name, bool $readonly): Ability
{
$ability = Mockery::mock(Ability::class);
$ability->allows('name')->andReturn($name);
$ability->allows('annotations')->andReturn(['readonly' => $readonly]);
return $ability;
}
private function gate(?FakeChangeLog $log = null): DiviToolGate
{
return new DiviToolGate(static fn (): array => self::GROUPS, $log);
}
private function untested(): void
{
ReleaseGate::useResolver(static fn (): ReleaseStatus => new ReleaseStatus(ReleaseState::Untested, '5.3.0'));
}
public function testReleasedDiviRefusesNothingAndAddsNothing(): void
{
$gate = $this->gate(FakeChangeLog::forbidden());
self::assertNull($gate->refusal($this->ability('lit/divi-insert', false)));
self::assertSame(['ok' => true], $gate->annotate($this->ability('lit/divi-outline', true), ['ok' => true]));
}
public function testWriteToolOfEveryDiviGroupIsRefused(): void
{
$this->untested();
$log = new FakeChangeLog();
$gate = $this->gate($log);
foreach (['lit/divi-insert', 'lit/library-save', 'lit/tb-create-template'] as $name) {
self::assertToolError($gate->refusal($this->ability($name, false)), 'divi_untested', $name);
}
self::assertNull($gate->refusal($this->ability('lit/content-create', false)), 'not a Divi tool (adapter lock)');
self::assertNull($gate->refusal($this->ability('lit/divi-outline', true)), 'reading stays allowed');
self::assertSame(['refused', 'refused', 'refused'], array_column($log->records, 'result'));
self::assertSame('Abgelehnt: Divi 5.3.0 ist nicht freigegeben.', $log->records[0]['summary']);
}
public function testReadResultsKeepTheirShapeAndGetTheNotice(): void
{
$this->untested();
$gate = $this->gate();
$read = $this->ability('lit/divi-outline', true);
$notice = 'Achtung: Divi 5.3.0 ist für LIT MCP ungetestet; Lesen funktioniert, Schreiben ist gesperrt.';
self::assertSame(['post_id' => 7, 'warnings' => [$notice]], $gate->annotate($read, ['post_id' => 7]));
self::assertSame(
['warnings' => ['alt', $notice]],
$gate->annotate($read, ['warnings' => ['alt']])
);
self::assertSame([1, 2], $gate->annotate($read, [1, 2]), 'a list stays a list');
$error = new WP_Error('lit_not_found', 'x');
self::assertSame($error, $gate->annotate($read, $error));
$other = $this->ability('lit/content-create', true);
self::assertSame(['post_id' => 7], $gate->annotate($other, ['post_id' => 7]));
}
public function testOutputSchemaAllowsWarnings(): void
{
$gate = $this->gate();
$read = $this->ability('lit/divi-outline', true);
$properties = ['post_id' => ['type' => 'integer']];
$schema = $gate->outputSchema($read, ['type' => 'object', 'properties' => $properties]);
$warnings = ['type' => 'array', 'items' => ['type' => 'string']];
self::assertSame($warnings, $schema['properties']['warnings'] ?? null);
$own = ['type' => 'object', 'properties' => ['warnings' => ['type' => 'array']]];
self::assertSame($own, $gate->outputSchema($read, $own), 'an existing warnings property stays');
self::assertNull($gate->outputSchema($read, null));
self::assertSame(
['type' => 'object'],
$gate->outputSchema($this->ability('lit/content-create', true), ['type' => 'object'])
);
}
}