feat(compat): Profile, Gates und Pods über den Kompatibilitätskern
Neu: Tier, Profile, Compatibility, CapabilityLocked, CapabilityGate, CompatibilityComponent, ProvidesCompatibility, DiviProfile sowie PodsFeature, PodsCompatibility und PodsIntegration. Das CapabilityGate sperrt gesperrte und unbekannte Fähigkeits-IDs (übernimmt die Sperre unbekannter IDs vom DiviFeatureGate) und delegiert nur Divi ausdrücklich. Pods-Schema, -Lesen, -Schreiben und -Feldrechte laufen über usable(PodsFeature::…); Schreiben verlangt FieldRead und FieldWrite, damit ein Rollback keine Werte verliert. lit-site-status meldet Pods über die CompatibilityComponent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
b511ef6348
commit
c85131603b
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Compatibility;
|
||||
|
||||
use Closure;
|
||||
use LIT\MCP\Compatibility\Call;
|
||||
use LIT\MCP\Compatibility\Compatibility;
|
||||
use LIT\MCP\Compatibility\CompatibilityComponent;
|
||||
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||
use LIT\MCP\Compatibility\Manifest;
|
||||
use LIT\MCP\Compatibility\Profile;
|
||||
use LIT\MCP\Compatibility\Tier;
|
||||
use LIT\MCP\Integrations\Core\EnvironmentComponent;
|
||||
use LIT\MCP\Tests\Support\FakeCapability;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use LogicException;
|
||||
|
||||
final class CompatibilityComponentTest extends TestCase
|
||||
{
|
||||
private function profile(bool $active, bool $broken = false): Profile
|
||||
{
|
||||
return new Profile(
|
||||
'fake',
|
||||
'Fake Plugin',
|
||||
Tier::LockOnFailure,
|
||||
[FakeCapability::Read, FakeCapability::Write],
|
||||
[new Manifest(
|
||||
'Fake',
|
||||
calls: $broken ? [new Call('lit_mcp_missing_function', 0, [FakeCapability::Write])] : []
|
||||
)],
|
||||
static fn (): bool => $active,
|
||||
static fn (): string => '4.2.0'
|
||||
);
|
||||
}
|
||||
|
||||
private function component(Profile $profile): EnvironmentComponent
|
||||
{
|
||||
return new CompatibilityComponent($profile, static fn (): Compatibility => new Compatibility([$profile]));
|
||||
}
|
||||
|
||||
public function testAnInactivePluginIsReportedAsNotInstalledWithoutProblems(): void
|
||||
{
|
||||
self::assertSame(
|
||||
['id' => 'fake', 'active' => false, 'version' => null, 'problems' => [], 'release' => null],
|
||||
$this->component($this->profile(false))->describe()
|
||||
);
|
||||
}
|
||||
|
||||
public function testAnActiveWorkingPluginHasItsVersionAndNoProblems(): void
|
||||
{
|
||||
self::assertSame(
|
||||
['id' => 'fake', 'active' => true, 'version' => '4.2.0', 'problems' => [], 'release' => null],
|
||||
$this->component($this->profile(true))->describe()
|
||||
);
|
||||
}
|
||||
|
||||
public function testAnActiveButBrokenPluginListsItsProblems(): void
|
||||
{
|
||||
$described = $this->component($this->profile(true, broken: true))->describe();
|
||||
|
||||
self::assertTrue($described['active']);
|
||||
self::assertSame('4.2.0', $described['version']);
|
||||
self::assertNotSame([], $described['problems']);
|
||||
self::assertContainsOnly('string', $described['problems']);
|
||||
self::assertNull($described['release']);
|
||||
}
|
||||
|
||||
public function testTheCompatibilityIsAskedOnlyWhenDescribing(): void
|
||||
{
|
||||
$asked = 0;
|
||||
$profile = $this->profile(true);
|
||||
$component = new CompatibilityComponent($profile, static function () use (&$asked, $profile): Compatibility {
|
||||
$asked++;
|
||||
|
||||
return new Compatibility([$profile]);
|
||||
});
|
||||
|
||||
self::assertSame(0, $asked);
|
||||
$component->describe();
|
||||
self::assertSame(1, $asked);
|
||||
}
|
||||
|
||||
public function testAReleasePerVersionProfileHasItsOwnComponent(): void
|
||||
{
|
||||
$profile = new Profile(
|
||||
'rel',
|
||||
'Rel',
|
||||
Tier::ReleasePerVersion,
|
||||
[FakeCapability::Other],
|
||||
matrix: static fn (): CompatibilityMatrix => CompatibilityMatrix::allReleased([FakeCapability::Other])
|
||||
);
|
||||
|
||||
$this->expectException(LogicException::class);
|
||||
|
||||
new CompatibilityComponent($profile, static fn (): Compatibility => new Compatibility([$profile]));
|
||||
}
|
||||
|
||||
public function testForProfilesBuildsAComponentPerProfileWithoutReleasePerVersion(): void
|
||||
{
|
||||
$plain = $this->profile(true);
|
||||
$release = new Profile(
|
||||
'rel',
|
||||
'Rel',
|
||||
Tier::ReleasePerVersion,
|
||||
[FakeCapability::Other],
|
||||
matrix: static fn (): CompatibilityMatrix => CompatibilityMatrix::allReleased([FakeCapability::Other])
|
||||
);
|
||||
|
||||
$components = CompatibilityComponent::forProfiles(new Compatibility([$release, $plain]));
|
||||
|
||||
self::assertSame(['fake'], array_map(static fn (CompatibilityComponent $c): string => $c->describe()['id'], $components));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user