Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
201 lines
8.7 KiB
PHP
201 lines
8.7 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||
|
||
use LIT\MCP\Integrations\Divi\Release\CompatibilityMatrix;
|
||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||
use LIT\MCP\Integrations\Divi\Release\FeatureStatus;
|
||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||
use LIT\MCP\Tests\Unit\TestCase;
|
||
use LogicException;
|
||
|
||
final class ReleaseStatusTest extends TestCase
|
||
{
|
||
public function testOnlyAReleasedVersionIsWritable(): void
|
||
{
|
||
self::assertTrue(ReleaseStatus::released('5.2.1')->writable());
|
||
self::assertFalse((new ReleaseStatus(ReleaseState::Untested, '5.3.0'))->writable());
|
||
self::assertFalse((new ReleaseStatus(ReleaseState::Incompatible, '5.3.0', null, ['x']))->writable());
|
||
}
|
||
|
||
public function testUntestedRefusalNamesTheVersionAndTheWayOut(): void
|
||
{
|
||
$payload = self::assertToolError(
|
||
(new ReleaseStatus(ReleaseState::Untested, '5.3.0'))->refusal(),
|
||
'divi_untested'
|
||
);
|
||
|
||
self::assertSame(
|
||
'Achtung: Divi 5.3.0 ist auf dieser Website noch nicht für LIT MCP freigegeben. Dieses Werkzeug braucht '
|
||
. 'Divi-Fähigkeiten, die noch nicht geprüft sind; andere Divi-Werkzeuge laufen weiter. Ein '
|
||
. 'Administrator kann unter Einstellungen → LIT MCP → Divi die Prüfung ausführen und die Version '
|
||
. 'freigeben. Es wurde nichts geändert.',
|
||
$payload['message']
|
||
);
|
||
self::assertStringContainsString('ein Werkzeug ohne die betroffene Fähigkeit nutzen', $payload['hint']);
|
||
self::assertStringContainsString('components → divi → features', $payload['hint']);
|
||
}
|
||
|
||
public function testIncompatibleRefusalListsTheProblems(): void
|
||
{
|
||
$status = new ReleaseStatus(ReleaseState::Incompatible, '5.3.0', null, ['Theme Builder: Nachbau von x()']);
|
||
$payload = self::assertToolError($status->refusal(), 'divi_incompatible');
|
||
|
||
self::assertSame(
|
||
'Divi 5.3.0 hat Stellen geändert, die LIT MCP für dieses Werkzeug nutzt; andere Divi-Werkzeuge laufen '
|
||
. 'weiter. Die betroffenen Werkzeuge bleiben gesperrt, bis LIT MCP aktualisiert wurde. Es wurde '
|
||
. 'nichts geändert.',
|
||
$payload['message']
|
||
);
|
||
self::assertSame(['Theme Builder: Nachbau von x()'], $payload['problems']);
|
||
}
|
||
|
||
public function testAReleasedStatusHasNoRefusal(): void
|
||
{
|
||
$this->expectException(LogicException::class);
|
||
|
||
ReleaseStatus::released('5.2.1')->refusal();
|
||
}
|
||
|
||
public function testToArrayForSiteStatus(): void
|
||
{
|
||
$status = new ReleaseStatus(
|
||
ReleaseState::Released,
|
||
'5.3.0',
|
||
ReleaseStatus::SOURCE_DATABASE,
|
||
[],
|
||
['released_at' => '2026-10-01T08:00:00+00:00', 'user_id' => 1]
|
||
);
|
||
|
||
self::assertSame(
|
||
['state' => 'released', 'version' => '5.3.0', 'source' => 'database',
|
||
'released_at' => '2026-10-01T08:00:00+00:00', 'released_by' => 1, 'problems' => []],
|
||
$status->toArray()
|
||
);
|
||
}
|
||
|
||
public function testWithoutMatrixEveryFeatureIsInTheGivenState(): void
|
||
{
|
||
$untested = new ReleaseStatus(ReleaseState::Untested, '5.3.0');
|
||
$broken = new ReleaseStatus(ReleaseState::Incompatible, '5.3.0', null, ['x']);
|
||
$released = ReleaseStatus::released('5.2.1', ReleaseStatus::SOURCE_DATABASE);
|
||
|
||
foreach (DiviFeature::cases() as $feature) {
|
||
self::assertSame(ReleaseState::Untested, $untested->matrix->of($feature)->state);
|
||
self::assertSame(['x'], $broken->matrix->of($feature)->problems);
|
||
self::assertSame('database', $released->matrix->of($feature)->source);
|
||
}
|
||
}
|
||
|
||
public function testOfTakesStateSourceAndProblemsFromTheMatrix(): void
|
||
{
|
||
$status = ReleaseStatus::of(
|
||
'5.99.0',
|
||
ReleaseMatrices::matrix([DiviFeature::Catalog], ReleaseState::Incompatible),
|
||
['user_id' => 1]
|
||
);
|
||
|
||
self::assertSame(ReleaseState::Incompatible, $status->state);
|
||
self::assertNull($status->source);
|
||
self::assertSame(['Seiten: et_x() – Signatur geändert'], $status->problems);
|
||
self::assertSame(['user_id' => 1], $status->release);
|
||
self::assertSame('auto', ReleaseStatus::of('5.99.0', CompatibilityMatrix::allReleased('auto'))->source);
|
||
}
|
||
|
||
public function testWritableAsksOnlyTheWritingFeatures(): void
|
||
{
|
||
$readLocked = ReleaseMatrices::status([DiviFeature::Catalog, DiviFeature::PageRead]);
|
||
self::assertSame(ReleaseState::Untested, $readLocked->state);
|
||
self::assertTrue($readLocked->writable());
|
||
|
||
foreach (CompatibilityMatrix::writeFeatures() as $feature) {
|
||
self::assertFalse(ReleaseMatrices::status([$feature])->writable(), $feature->value);
|
||
}
|
||
}
|
||
|
||
public function testAMatrixInAnotherStateThanTheStatusIsRefused(): void
|
||
{
|
||
$this->expectException(LogicException::class);
|
||
|
||
new ReleaseStatus(ReleaseState::Released, '5.2.1', 'code', [], null, CompatibilityMatrix::allIncompatible('x'));
|
||
}
|
||
|
||
public function testRefusalForAnUntestedFeatureNamesItAndKeepsTheOthersWorking(): void
|
||
{
|
||
$error = ReleaseMatrices::status([DiviFeature::PageWrite])
|
||
->refusalFor([DiviFeature::PageWrite, DiviFeature::PageRead]);
|
||
$payload = self::assertToolError($error, 'divi_untested');
|
||
|
||
self::assertSame(423, $error->get_error_data()['status']);
|
||
|
||
self::assertSame(
|
||
'Achtung: Divi 5.3.0 ist auf dieser Website für „Seiten schreiben“ noch nicht für LIT MCP freigegeben. '
|
||
. 'Das ist gesperrt, bis ein Administrator unter Einstellungen → LIT MCP → Divi die Prüfung ausführt '
|
||
. 'und die Version freigibt. Es wurde nichts geändert.',
|
||
$payload['message']
|
||
);
|
||
self::assertSame(
|
||
'Gesperrt: „Seiten schreiben“. Andere Divi-Werkzeuge funktionieren weiter, sofern ihre Fähigkeiten '
|
||
. 'freigegeben sind. Den Nutzer bitten, die Divi-Prüfung auszuführen und die Version freizugeben.',
|
||
$payload['hint']
|
||
);
|
||
self::assertSame(
|
||
[['id' => 'page-write', 'label' => 'Seiten schreiben', 'state' => 'untested', 'problems' => []]],
|
||
$payload['features']
|
||
);
|
||
self::assertArrayNotHasKey('problems', $payload);
|
||
}
|
||
|
||
public function testRefusalForTakesTheWorstStateAndListsEveryLockedFeature(): void
|
||
{
|
||
$matrix = ReleaseMatrices::matrix([DiviFeature::ThemeBuilderWrite], ReleaseState::Incompatible);
|
||
$features = [];
|
||
foreach (DiviFeature::cases() as $feature) {
|
||
$features[$feature->value] = $matrix->of($feature);
|
||
}
|
||
$features['library-write'] = new FeatureStatus(DiviFeature::LibraryWrite, ReleaseState::Untested);
|
||
$status = ReleaseStatus::of('5.99.0', new CompatibilityMatrix($features));
|
||
|
||
$payload = self::assertToolError(
|
||
$status->refusalFor([DiviFeature::PageWrite, DiviFeature::LibraryWrite, DiviFeature::ThemeBuilderWrite]),
|
||
'divi_incompatible'
|
||
);
|
||
|
||
self::assertSame(
|
||
'Divi 5.99.0 hat Stellen geändert, die LIT MCP für „Theme Builder schreiben“ nutzt. Das ist gesperrt, bis '
|
||
. 'LIT MCP aktualisiert wurde. Es wurde nichts geändert.',
|
||
$payload['message']
|
||
);
|
||
self::assertStringStartsWith(
|
||
'Gesperrt: „Bibliothek schreiben“ und „Theme Builder schreiben“. Andere Divi-Werkzeuge',
|
||
$payload['hint']
|
||
);
|
||
self::assertStringEndsWith('dass LIT MCP aktualisiert werden muss.', $payload['hint']);
|
||
self::assertSame(['library-write', 'tb-write'], array_column($payload['features'], 'id'));
|
||
self::assertSame(['untested', 'incompatible'], array_column($payload['features'], 'state'));
|
||
self::assertSame(['Seiten: et_x() – Signatur geändert'], $payload['problems']);
|
||
}
|
||
|
||
public function testRefusalForNamesThreeFeatures(): void
|
||
{
|
||
$locked = [DiviFeature::PageWrite, DiviFeature::LibraryWrite, DiviFeature::PresetWrite];
|
||
$payload = self::assertToolError(ReleaseMatrices::status($locked)->refusalFor($locked), 'divi_untested');
|
||
|
||
self::assertStringStartsWith(
|
||
'Gesperrt: „Seiten schreiben“, „Bibliothek schreiben“ und „Presets schreiben“.',
|
||
$payload['hint']
|
||
);
|
||
}
|
||
|
||
public function testUsableFeaturesHaveNoRefusal(): void
|
||
{
|
||
$this->expectException(LogicException::class);
|
||
|
||
ReleaseMatrices::status([DiviFeature::Catalog])->refusalFor([DiviFeature::PageWrite, DiviFeature::PageRead]);
|
||
}
|
||
}
|